一、实现原理

        在 QML 中实现无边框且可以拖动的窗口,要比 Qt PyQt 简单的多。只要隐藏掉窗体、去掉标题栏,然后用一个和原窗体相同大小的 Rectangle 作为新窗体。

        最后在新窗体上再加一个小一些的 Rectangle 作为标题栏,在标题栏中放一个 MouseArea 来监测鼠标位置,同时更新窗体的位置,即 x值即可。

QML无边框窗口(可拖动)-LMLPHP二、具体步骤步骤

1. 去掉标题栏、隐藏窗体

        color 属性设置为透明即可,防止后面覆盖上来的 Rectangle 有黑边。

flags: Qt.FramelessWindowHint
color: "#00000000"
2. 用Rectangle替代原窗体

        要使 Rectangle 能覆盖原窗口,只要把它的宽高设置成和原窗体的宽高一致即可。然后我给它又加了圆角和渐变。如果你不需要圆角,那上面步骤中的 color 属性可以不用设置。

    Rectangle
    {
        width: parent.width
        height: parent.height

        gradient: Gradient
        {
            GradientStop{ position: 0.0; color:"#1f005c"}
            GradientStop{ position: 1.0; color:"#ffb56b"}
        }

        radius: 15

        ...
}
3. 新的标题栏,实现拖动

        做到第二步,窗体还不能拖动,是一块固定区域。一般软件的窗体都是通过鼠标按住标题栏,然后移动鼠标,从而窗体跟随鼠标移动,松开鼠标时则窗体停留在此处。

        标题栏实现很简单,就是再用一个 Rectangle 来替代就行,这个 Rectangle 和窗体的 Rectangle 是等宽不等高的,高度需要多少,你可以自己设置。

        因为标题栏一般都在窗体的顶部,所以我们将这2个 Rectangle 的顶部锚定在一起。

        在标题栏中,我们填充一个 MouseArea,在这个 MouseArea 中我们要监测鼠标的3种状态,分别是:按下、松开、位置移动。

        在按下状态时,我们获取鼠标的位置。在松开的时候判断鼠标是否移动,在鼠标移动时,我们将鼠标当前位置减去原窗体位置并赋值给窗体的 xy,即实现了鼠标拖动窗体的功能。

        这一步的代码比较长,小伙伴们可以对照下面的完整代码来理解,我就不一一拆开说明了。

三、完整代码

import QtQuick
import QtQuick.Controls

Window {
    id: root
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    color: "#00000000"
    flags: Qt.FramelessWindowHint

    property int dragX: 0
    property int dragY: 0
    property bool dragging: false

    Rectangle
    {
        width: parent.width
        height: parent.height

        gradient: Gradient
        {
            GradientStop{ position: 0.0; color:"#1f005c"}
            GradientStop{ position: 1.0; color:"#ffb56b"}
        }

        radius: 15

        Rectangle
        {
            width: parent.width
            height: 50
            color: "grey"
            anchors.top: parent.top

            MouseArea
            {
                anchors.fill: parent
                onPressed:
                {
                    root.dragX = mouseX
                    root.dragY = mouseY
                    root.dragging = true
                }
                onReleased: root.dragging = false
                onPositionChanged:
                {
                    if(root.dragging)
                    {
                        root.x += mouseX - root.dragX
                        root.y += mouseY - root.dragY
                    }
                }
            }
        }
    }
}

四、结语

        码字不易,如果对你有所帮助,请随手点个赞吧!我还会继续更新有关 QML 的更多知识与技巧,如果你也有兴趣,可以再关注我一下,感谢!

 

03-22 21:28