在 qml 中拖动无框窗口“抖动”
Posted
技术标签:
【中文标题】在 qml 中拖动无框窗口“抖动”【英文标题】:Dragging frameless window "jiggles" in qml 【发布时间】:2016-08-22 21:15:39 【问题描述】:我有一个无框架的 ApplicationWindow,我想使用this 问题的答案使其可拖动。然而,正如有人在评论中所说,当我快速移动窗口时,它会抖动很多。
我一直在尝试改进它,但没有成功。
ApplicationWindow
visible: true
width: 640
height: 480
title: qsTr("WIP")
id: mainWindow
flags: Qt.SubWindow | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowSystemMenuHint
header: ToolBar
MouseArea
anchors.fill: parent
onDoubleClicked: mainWindow.visibility!="2"?mainWindow.showNormal():mainWindow.showMaximized()
id: maMainWindow
property variant clickPos: "0,0"
onPressed:
clickPos = Qt.point(mouse.x,mouse.y)
onPositionChanged:
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
mainWindow.x += delta.x;
mainWindow.y += delta.y;
如果我添加标签和一些元素,情况会变得更糟。
C++ 能否以某种方式提高其性能?
【问题讨论】:
导入QtQuick.Window
可能有助于Window.Visibility
枚举。
根据 relative 提供的按下和移动坐标计算 全局 窗口坐标的增量听起来不是一个好主意鼠标区域。如果下面的窗户一移动,事情就会向南移动,我并不感到惊讶。 :)
我正在导入 QtQuick.Window 2.0,但我不明白使用可见性枚举是什么意思。您可以添加一个替代方法来计算全局窗口的增量吗?
【参考方案1】:
我遇到了同样的问题,性能还可以,但是在 linux 上它在整个屏幕上跳跃并“抖动”。我已经通过在 C++ 中编写一个帮助程序类来解决它,我已经将它公开为 QML 上下文属性。这个解决方案对我帮助很大。我有非常复杂的用户界面,它工作得非常好,性能非常好。 所以让我们开始吧。 1) 你需要一个类似这样的辅助类:
class CursorPosProvider : public QObject
Q_OBJECT
public:
explicit CursorPosProvider(QObject *parent = nullptr) : QObject(parent)
virtual ~CursorPosProvider() = default;
Q_INVOKABLE QPointF cursorPos()
return QCursor::pos();
;
这是一个非常简单的类,它只从 C++ 端为您提供光标位置,这很奇怪,但是当您在 QML 中执行相同操作时,您会遇到问题(至少在 linux 上)。 2) 将其作为上下文属性公开给 QML 引擎,我已经通过以下方式完成了:
int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQuickView view;
CursorPosProvider mousePosProvider;
view.rootContext()->setContextProperty("mousePosition", &mousePosProvider);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
3) 好的,现在我们已经准备好使用 QML 部分了。 我有一个 Qt Quick 组件,它为无框窗口实现了 TitleBar,如下所示:
Rectangle
id: root
width: parent.width
color: "#0099d6" // just random one
property QtObject container
// extra properties, maybe some signals
MouseArea
id: titleBarMouseRegion
property var clickPos
anchors.fill: parent
onPressed:
clickPos = x: mouse.x, y: mouse.y
onPositionChanged:
container.x = mousePosition.cursorPos().x - clickPos.x
container.y = mousePosition.cursorPos().y - clickPos.y
4) 现在你可以在任意窗口中使用这个 TitleBar 了:
Window
id: root
visible: true
flags: Qt.FramelessWindowHint
TitleBar
height: 20
container: root
Text
text: qsTr("Hello World")
anchors.centerIn: parent
当我为标题栏实现拖放时,主要问题是 QML 提供的绳索,这个解决方案解决了这个问题。 如果我的解决方案对您有帮助,请提供一些反馈。我真的很感兴趣:)
【讨论】:
【参考方案2】:我认为您无能为力,这只是使用绑定构建 GUI 的副作用,并且绑定评估与渲染不同步。结果,当您移动或调整窗口大小时,一切都像弹性一样摇摆不定,直到值“赶上”。这是 QML 的事情,在小部件中你不会得到那种行为,因为 UI 不是围绕绑定构建的。基本上,每个绑定链的评估都存在延迟,当 GUI 绘制时,它会捕获并显示绑定链传播的延迟,链中的第一个对象已经在它们的新位置,而那些更远的向后可以在传播中落后几个步骤。当然,您的窗户是否有框架与该问题完全无关。
克服这一点需要控制绑定如何处理信号,我认为目前没有这样的事情。基本上,诀窍是以某种方式强制绘制等到链中的每个绑定都被评估,并在启动另一系列评估之前绘制。
自然,您拥有的元素越多,每次更改将级联所有这些元素所需的时间就越长,从而使效果更加明显。它还取决于您的系统有多快——因为这决定了评估绑定链的延迟,例如我的系统很快,而您的示例代码不会产生抖动。然而,虽然在调整大小期间发生这种情况是可以理解的,但它引出了一个问题,为什么当您只是移动窗口时会发生这种情况。毕竟,这不应该真正改变窗口中 UI 元素的相对位置。我怀疑发生这种情况是因为在内部这些对象是在“绝对屏幕空间”中绘制的,因此当您移动窗口时,这会导致每个元素的实际绝对位置发生变化,即使它们相对于窗口保持在同一位置,从而导致这种行为。不理想...不仅引入了不受欢迎的视觉行为,而且还引入了许多额外的评估,这些评估似乎是不必要的开销。
请注意,这些只是我的模糊怀疑,我没有详细调查此事,希望有人可以提供一种快速简便的方法来处理这个问题。现在我忽略了这个问题,希望它不会太烦人,考虑到我关注的软件不是关于窗口位置和几何形状的连续变化;)顺便说一句,即使我第一次在 QML 中看到这个,在过去的几年里,我确实在其他“现代 gui”框架中也注意到了它。这是可以理解的,因为这些框架为了快速原型设计而转向性能较慢的语言,并结合“流畅”的异步非阻塞渲染。
【讨论】:
使用我帖子的代码,它会稍微抖动,但如果我添加一些元素,性能就会下降。让我们希望其他人已经找到了改善这种行为的方法。 绑定不是异步的。 @jpnurmi 我没有正确用词,我的意思是它与渲染不同步。以上是关于在 qml 中拖动无框窗口“抖动”的主要内容,如果未能解决你的问题,请参考以下文章
JAVA_swing抖动窗口,要求在拖动窗口位置后能在新位置进行抖动!请看代码...