10

I’m looking for a way of dragging frameless window in QtQuick2. I followed this thread on the forum Link but it gives me an error.

Main difference in the code is that my code uses QtQuick2ApplicationViewer instead of QmlApplicationViewer and it looks like QtQuick2ApplicationViewer do not have “.pos” property.

This is my main.cpp

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QQmlContext>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.rootContext()->setContextProperty("QmlApplicationViewer", (QObject *)&viewer);
    viewer.setFlags(Qt::FramelessWindowHint);
    viewer.setMainQmlFile(QStringLiteral("qml/ubusell/main.qml"));
    viewer.showExpanded();

    return app.exec();
}

This is part of my main.qml

MouseArea {
    id: mouseRegion
    anchors.fill: parent;
    property variant clickPos: "1,1"

        onPressed: {
            clickPos  = Qt.point(mouse.x,mouse.y)
        }

        onPositionChanged: {
            var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
            print(QmlApplicationViewer.pos)
            QmlApplicationViewer.pos = (20,20)
            QmlApplicationViewer.pos = Qt.point(QmlApplicationViewer.pos.x+delta.x,
                              QmlApplicationViewer.pos.y+delta.y)
        }
}

When I try to drag window I get this error:

TypeError: Cannot read property 'x' of undefined

Any ideas ? Is it even possible with QtQuick2 ? Thanks for help!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Majster-pl
  • 148
  • 1
  • 1
  • 8
  • https://stackoverflow.com/questions/18754057/shadow-for-qml-frameless-windows/40442357#40442357 – dtech Nov 30 '21 at 06:37

5 Answers5

21

In my project I do:

property variant clickPos: "1,1"

onPressed: {
    clickPos  = Qt.point(mouse.x,mouse.y)
}

onPositionChanged: {
    var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
    rootWindow.x += delta.x;
    rootWindow.y += delta.y;
}

In MouseArea.

Noah
  • 95
  • 1
  • 14
Dcow
  • 1,413
  • 1
  • 19
  • 42
4

Also to resemble Windows behaviour of maximizing window when dragging it above vertical edge of the screen:

MouseArea {
    anchors.fill: parent;
    property variant clickPos: "1,1"

    onPressed: {
        clickPos = Qt.point(mouse.x,mouse.y)
    }

    onPositionChanged: {
        var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
        var new_x = mainWindow.x + delta.x
        var new_y = mainWindow.y + delta.y
        if (new_y <= 0)
            mainWindow.visibility = Window.Maximized
        else
        {
            if (mainWindow.visibility === Window.Maximized)
                mainWindow.visibility = Window.Windowed
            mainWindow.x = new_x
            mainWindow.y = new_y
        }
    }
}
DikobrAz
  • 3,557
  • 4
  • 35
  • 53
1

I done it as follow:

Window {
    id: window
    height: 400
    width: 250
    x: (Screen.width - width)/2     //<---start position of window
    y: (Screen.height - height)/2   //<-┘
    color: "transparent"
    flags: Qt.MSWindowsFixedSizeDialogHint | Qt.FramelessWindowHint

    MouseArea {
        anchors.fill: parent
        property point lastMousePos: Qt.point(0, 0)
        onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
        onMouseXChanged: window.x += (mouseX - lastMousePos.x)
        onMouseYChanged: window.y += (mouseY - lastMousePos.y)
    }

    Item {
        id: myFirstPage
        anchors.fill: parent
        anchors.topMargin: 50
        //...
        //This item can have some mouse area
    }
}

Now you can move window using dragging top 50 pixels or any where that is not under any MouseArea.

S.M.Mousavi
  • 5,013
  • 7
  • 44
  • 59
1

A rather complete example:

import QtQuick 2.14
import QtQuick.Controls 2.14

ApplicationWindow {
    visible: true
    width: 200
    height: 200
    flags: Qt.FramelessWindowHint
    MouseArea {
        anchors.fill: parent
        onPressed: { pos = Qt.point(mouse.x, mouse.y) }
        onPositionChanged: {
            var diff = Qt.point(mouse.x - pos.x, mouse.y - pos.y)
            ApplicationWindow.window.x += diff.x
            ApplicationWindow.window.y += diff.y
        }
        property point pos
    }
}
1

It looks like the startSystemMove() method is specifically intended for this.

Runnable example, based on what MauiKit does:

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15

Window {
    id: root
    flags: Qt.FramelessWindowHint
    visible: true
    width: 300
    height: 300
    Item {
        id: _dragHandler
        anchors.fill: parent
        DragHandler {
            acceptedDevices: PointerDevice.GenericPointer
            grabPermissions:  PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything
            onActiveChanged: if (active) root.startSystemMove()
        }
    }
}

This handles mouse drags/interactions that aren't used by anything else.

The docs say this is preferable to manually changing the window position, because it integrates better with the desktop and may work on more platforms:

On platforms that support it, this method of moving windows is preferred over setPosition, because it allows a more native look-and-feel of moving windows, e.g. letting the window manager snap this window against other windows, or special tiling or resizing behavior with animations when dragged to the edge of the screen. Furthermore, on some platforms such as Wayland, setPosition is not supported, so this is the only way the application can influence its position.

Will Chen
  • 482
  • 4
  • 12