简体   繁体   English

在qml中拖动无框窗口“jiggles”

[英]Dragging frameless window “jiggles” in qml

I have a frameless ApplicationWindow and I wanted to make it draggable using the answer of this question. 我有一个无框架的ApplicationWindow,我想用这个问题的答案让它成为可拖动的。 However, as someone said in a comment, when I move the window fastly, it jiggles a lot . 然而,正如有人在评论中所说, 当我快速移动窗口时,它会摇晃很多

I've been trying to improve it but without success. 我一直在努力改进它,但没有成功。

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 I add tabs and some elements it makes it worse. 如果我添加标签和一些元素会使情况变得更糟。

Can C++ improve its performance somehow? C ++可以以某种方式改善其性能吗?

I had the same problem, the performance was ok, but on linux it was jumping all over the screen and "jiggling". 我遇到了同样的问题,性能还可以,但是在linux上,它在屏幕上跳跃并“摇摇晃晃”。 I have solved it by writing a helper class in C++ which I have exposed as QML context property. 我已经通过在C ++中编写一个帮助器类来解决它,我将它作为QML上下文属性公开。 This solution helped me a lot. 这个解决方案给了我很多帮助。 I have very complex UI and it works perfectly fine, with very good performance. 我有非常复杂的用户界面,它工作得很好,性能非常好。 So lets get started. 让我们开始吧。 1) You will need a helper class something like this: 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();
    }
};

It is a really simple class which just provides you cursor position from C++ side, it is strange, but when you do the same in QML you get problems(at least on linux). 这是一个非常简单的类,只是从C ++端提供光标位置,这很奇怪,但是当你在QML中做同样的事情时,你会遇到问题(至少在linux上)。 2) Expose it as context property to QML engine, I have done it in next way: 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) Ok, now we are ready to go with QML part. 3)好的,现在我们准备好了QML部分。 I have a Qt Quick component that implements a TitleBar for frameless window, like this: 我有一个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) Now you are ready to use this TitleBar in arbitrary window in next way: 4)现在您已准备好在下一个方向中在任意窗口中使用此TitleBar:

Window {
    id: root
    visible: true

    flags: Qt.FramelessWindowHint

    TitleBar {
        height: 20
        container: root
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
}

When I was implementing drag&drop for title bar the main problem is in cords that QML provides, this solution fixes that issue. 当我为标题栏实现拖放时,主要问题在于QML提供的线索,此解决方案修复了该问题。 Please provide some feedback if my solution will help you. 如果我的解决方案能为您提供帮助,请提供反馈。 I'm really interested:) 我真的很感兴趣:)

I don't think there is anything you can do, it is just a side effect of using bindings to build the GUI and binding evaluations are not synchronized with rendering. 我认为你无法做任何事情,这只是使用绑定来构建GUI并且绑定评估与渲染不同步的副作用。 As a result, as you move or resize the window, everything is wobbling around like elastic until the value "catches up". 结果,当您移动窗口或调整窗口大小时,一切都像弹性一样摇晃,直到值“赶上”。 That's a QML thing, in widgets you don't get that kind of behavior because the UI is not build around bindings. 这是一个QML的东西,在小部件中你没有得到那种行为,因为UI不是围绕绑定构建的。 Basically, there is delay involved in the evaluation of every chain of bindings, and as the GUI is draw it catches and displays the delay in propagation of the binding chain, the first objects from the chain are already in their new locations, while those further towards the back can be behind by several steps in the propagation. 基本上,每个绑定链的评估都有延迟,并且由于GUI是绘制它捕获并显示绑定链传播的延迟,链中的第一个对象已经在它们的新位置,而那些进一步向后可以通过传播的几个步骤落后。 And naturally, whether your window has frames is totally irrelevant to that issue. 当然,你的窗户是否有框架与这个问题完全无关。

Overcoming this would require control over how signals are being handled by the bindings, and I don't think there is currently such a thing. 克服这一点需要控制绑定如何处理信号,我认为目前没有这样的事情。 Basically, the trick is to somehow force drawing to wait until every binding in the chain is evaluated, and draw in between before another series of evaluations is initiated. 基本上,诀窍是以某种方式迫使绘图等待,直到链中的每个绑定被评估,并在启动另一系列评估之前介入。

Naturally, the more elements you have the longer each change would take to cascade through all of them, making the effect more pronounced. 当然,你拥有的元素越多,每次变化所需的时间越长,所有这些变化都会更加明显。 It also depends on how fast your system is - as that determines the delay in evaluating the binding chain, for example my system is fast and your example code does not produce the jiggling. 它还取决于你的系统有多快 - 因为这决定了评估绑定链的延迟,例如我的系统很快,你的示例代码不会产生抖动。 However, while it is understandable that this happens during resizing, it begs the question why it is happening when you are simply moving the window around. 然而,虽然在调整大小期间发生这种情况是可以理解的,但是当你只是简单地移动窗口时,它就会引发一个问题。 After all, that's shouldn't really be changing the relative positions of the UI elements in the window. 毕竟,这不应该真正改变窗口中UI元素的相对位置。 I suspect this happens because internally those objects are drawn in "absolute screen space", so as you move the window, this causes the actual absolute positions of every element to change even if they remain in the same place relative to the window, resulting in this behavior. 我怀疑这是因为内部的那些对象是在“绝对屏幕空间”中绘制的,所以当您移动窗口时,这会导致每个元素的实际绝对位置发生变化,即使它们保持在相对于窗口的相同位置,从而导致这种行为。 Not ideal... Not only does introduce that undesired visual behavior, but also a lot of additional evaluations which seem like unnecessary overhead. 不理想......不仅会引入不受欢迎的视觉行为,还会产生许多额外的评估,这些评估似乎是不必要的开销。

Note that those are just my vague suspicions, I haven't investigated the matter in detail, hopefully someone might offer a quick and easy way to deal with this. 请注意,这些只是我的模糊怀疑,我没有详细调查此事,希望有人可以提供一种快速简便的方法来处理这个问题。 For now I am ignoring this issue, hoping that it wouldn't be too annoying, considering that I focus on software which is not about continuous changes in the position and geometry of the window ;) BTW even though I first saw this in QML, the last few years I did notice it in other "modern gui" frameworks as well. 现在我忽略了这个问题,希望它不会太烦人,因为我专注于软件而不是窗口的位置和几何形状的连续变化;)BTW即使我第一次在QML中看到这个,在过去的几年里,我也注意到了其他“现代gui”框架。 It would be understandable as such frameworks move to slower performing languages for the sake of rapid prototyping, combined with "fluid" asynchronous non-blocking rendering. 这是可以理解的,因为为了快速原型设计,这种框架转向性能较低的语言,并结合“流畅的”异步非阻塞渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM