Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dragging frameless window "jiggles" in qml

Tags:

c++

qt

qml

qtquick2

I have a frameless ApplicationWindow and I wanted to make it draggable using the answer of this question. 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?

like image 719
Abdelilah El Aissaoui Avatar asked Aug 22 '16 21:08

Abdelilah El Aissaoui


1 Answers

I had the same problem, the performance was ok, but on linux it was jumping all over the screen and "jiggling". I have solved it by writing a helper class in C++ which I have exposed as QML context property. 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:

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). 2) Expose it as context property to QML engine, I have done it in next way:

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. I have a Qt Quick component that implements a TitleBar for frameless window, like this:

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:

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. Please provide some feedback if my solution will help you. I'm really interested:)

like image 86
durkmurder Avatar answered Oct 30 '22 22:10

durkmurder