Dragging jiggles frameless window into qml

I have a frameless ApplicationWindow, and I wanted to make it draggable using the answer to this question. However, as someone in the commentary said, when I quickly go to the window, it shifts a lot.

I try to improve it, but to no avail.

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; } } } } 

If you add tabs and some elements, it will be even worse.

Can C ++ improve its performance in some way?

Thanks!

+4
source share
2 answers

I had the same problem, the performance was fine, but on Linux it jumped across the screen and swayed. I solved this by writing a helper class in C ++, which I expanded as a QML context property. This solution helped me a lot. I have a very complicated interface and it works great, with very good performance. So let's get started. 1) You will need a helper class:

 class CursorPosProvider : public QObject { Q_OBJECT public: explicit CursorPosProvider(QObject *parent = nullptr) : QObject(parent) { } virtual ~CursorPosProvider() = default; Q_INVOKABLE QPointF cursorPos() { return QCursor::pos(); } }; 

This is a really simple class that just provides you with a cursor position on the C ++ side, this is strange, but when you do the same in QML, you get problems (at least in Linux). 2) Designate it as a context property for the QML mechanism, I did it as follows:

 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) Well, now we are ready to go with the QML part. I have a Qt Quick component that implements a TitleBar for a boundless window, for example:

 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) Now you are ready to use this TitleBar in an arbitrary window as follows:

 Window { id: root visible: true flags: Qt.FramelessWindowHint TitleBar { height: 20 container: root } Text { text: qsTr("Hello World") anchors.centerIn: parent } } 

When I was doing drag & drop for the title, the main problem was the bundles provided by QML, this solution fixes this problem. Please provide some feedback if my solution helps you. It is very interesting to me:)

+3
source

I don’t think there is anything you can do, it’s just a side effect of using bindings to build a GUI, and binding estimates are not synchronized with the rendering. As a result, when you move or resize the window, everything vibrates like elastic until the value "reaches". Something like QML, in widgets you don't get this behavior because the user interface is not built around bindings. In principle, there is a delay associated with the evaluation of each chain of bindings, and as the graphical interface attracts and displays the delay in the distribution of the connecting chain, the first objects from the chain are already in their new locations, while those to the back may be slightly behind distribution steps. And, of course, regardless of whether your window has frames, this has nothing to do with this problem.

Overcoming this will require control over how the signals are processed by the bindings, and I don't think such a thing at present. In principle, the trick is to somehow make the drawing wait until each binding in the chain has been evaluated, and draw between them before another series of evaluations is initiated.

Naturally, the more elements you have, the more changes there will be to cascade them all, making the effect more pronounced. It also depends on how fast your system is - because it determines the delay in evaluating the anchor chain, for example, my system is fast and your sample code does not cause bias. However, while it’s clear that this happens when you resize, the question arises as to why this happens when you simply move the window around. In the end, this should not really change the relative position of the user interface elements in the window. I suspect that this is because these objects are drawn inside the “absolute screen space” from the inside, since you move the window, this leads to a change in the actual absolute positions of each element, even if they remain in the same place relative to the window, which leads to this behavior. Not perfect ... Not only introduces this unwanted visual behavior, but also many additional ratings that seem like unnecessary overhead.

Please note that these are only my vague suspicions, I did not investigate the issue in detail, I hope someone can offer a quick and easy way to handle this. At the moment, I ignore this problem, hoping that it will not be too annoying, given that I focus on software that is not associated with constant changes in the position and geometry of the window;) By the way, although I first saw this in QML, Over the past few years, I have noticed this in other "modern gui." It would be understood that such a framework is moving to slower languages ​​for rapid prototyping in combination with fluid asynchronous non-blocking rendering.

0
source

All Articles