QtQuick2 перетаскивая безрамное окно

Я ищу способ перетаскивания безрамного окна в QtQuick2. Я следил за этой веткой на форуме Link, но она выдает ошибку.

Основное отличие в коде состоит в том, что мой код использует QtQuick2ApplicationViewer вместо QmlApplicationViewer и похоже QtQuick2ApplicationViewer не имеют свойства ".pos".

Это мой 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();
}

Это часть моего 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)
        }
}

Когда я пытаюсь перетащить окно, я получаю эту ошибку:

Ошибка типа: невозможно прочитать свойство 'x' из неопределенного

Есть идеи? Это возможно с QtQuick2? Спасибо за помощь!

5 ответов

Решение

В моем проекте я делаю:

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

В MouseArea,

Также, чтобы походить на поведение Windows при максимизации окна при перетаскивании его над вертикальным краем экрана:

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

Похоже,Метод специально предназначен для этого.

Запускаемый пример, основанный на том, что делает MauiKit :

      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()
        }
    }
}

Это обрабатывает перетаскивание/взаимодействия мыши, которые не используются ничем другим.

В документах говорится, что это предпочтительнее, чем изменение положения окна вручную, поскольку оно лучше интегрируется с рабочим столом и может работать на большем количестве платформ:

На платформах, которые его поддерживают, этот метод перемещения окон предпочтительнее , потому что он обеспечивает более естественный внешний вид движущихся окон, например позволяя оконному менеджеру привязывать это окно к другим окнам, или специальное поведение плитки или изменения размера с анимацией. при перетаскивании к краю экрана. Кроме того, на некоторых платформах, таких как Wayland, не поддерживается, так что это единственный способ, которым приложение может влиять на свое положение.

Я сделал это следующим образом:

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

Теперь вы можете перемещать окно, перетаскивая верхние 50 пикселей или в любое место, которое не находится ни под каким MouseArea.

Довольно полный пример:

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
    }
}
Другие вопросы по тегам