QML实现的无边框窗口的拉伸,拖拽,基本解决闪烁严重问题

【正文开始】

注意本篇所讲方法过于辣鸡,新方法见:QmlControls/FramelessWindow at master · mengps/QmlControls · GitHub

这段话是后来加的。。

        使用 Qt 制作的无边框窗口,只需在其 flag 中加入 FramelessWindowHint

        然而,无边框窗口意味着,无法使用原有的边框拉伸,拖拽功能。

        在 QWidget 中,有很多实现的方法,比如重写

        + mouseMoveEvent(QMouseEvent *event)

        + mousePressEvent(QMouseEvent *event)

        + mouseReleaseEvent(QMouseEvent *event)

        这几个事件即可很容易的完成无边框窗口的拉伸,拖拽功能。ps :重写 nativeEvent(const QByteArray &eventType, void *message, long *result) 可以获得最好的效果~

        但是在 Qml 中,由于 QWindow QWidget 的实现方式完全不同,而 QQuickwindow 继承自 QWindow,使用上述的方法当然也可以如 widget 一样的工作,然鹅经过测试闪烁严重,体验极差,于是就有了另一种方法。

        直接使用 MouseArea 进行拉伸,拖拽。

        qml 代码如下:

import QtQuick 2.7

/*
             ↑     ↑     ↑
           ←|1|   |2|   |3|→
           ←|4|   |5|   |6|→
           ←|7|   |8|   |9|→
             ↓     ↓     ↓
            分8个缩放区域
            |5|为拖动区域
       target       缩放目标
       startPoint   鼠标起始点
       fixedPont    用于固定窗口的点
       每一个area   大小 8 x 8
*/

Item
{
    id: area

    property var target: undefined;
    property point startPoint: Qt.point(0, 0);
    property point fixedPont: Qt.point(0, 0);

    MouseArea
    {
        id: area1
        x: 0
        y: 0
        width: 8
        height: 8
        hoverEnabled: true

        onEntered: cursorShape = Qt.SizeFDiagCursor;
        onExited: cursorShape = Qt.ArrowCursor;
        onPressed: startPoint = Qt.point(mouseX, mouseY);
        onPositionChanged:
        {
            if(pressed)
            {
                var offsetX = mouse.x - startPoint.x;
                var offsetY = mouse.y - startPoint.y;
                if ((target.width - offsetX) >= target.minimumWidth) //如果本次调整小于最小限制,则调整为最小
                {
                    target.width -= offsetX;
                    target.x += offsetX;
                }
                else
                {
                    target.x += (target.width - target.minimumWidth);
                    target.width -= (target.width - target.minimumWidth);
                }

                if ((target.height - offsetY) >= target.minimumHeight && offsetY != 0)
                {
                    target.height -= offsetY;
                    target.y += offsetY;
                }
            }
        }
    }

    MouseArea
    {
        id: area2
        x: 8
        y: 0
        width: target.width - 16
        height: 8
        hoverEnabled: true

        onEntered: cursorShape = Qt.SizeVerCursor;
        onExited: cursorShape = Qt.ArrowCursor;
        onPressed: startPoint = Qt.point(mouseX, mouseY);
        onPositionChanged:
        {
            if(pressed)
            {
                var offsetY = mouse.y - startPoint.y;
                if ((target.height - offsetY) >= target.minimumHeight && offsetY != 0)
                {
                    target.height -= offsetY;
                    target.y += offsetY;
                }
            }
        }
    }

    MouseArea
    {
        id: area3 
        x: target.width - 8
        y: 0
        width: 8
        height: 8
        hoverEnabled: true

        onEntered: cursorShape = Qt.SizeBDiagCursor;
        onExited: cursorShape = Qt.ArrowCursor
        onPressed:
        {
            startPoint = Qt.point(mouseX, mouseY);
            fixedPont = Qt.point(target.x, target.y)
        }
        onPositionChanged:
        {
            if(pressed)
            {
                var offsetX = mouse.x - startPoint.x;
                var offsetY = mouse.y - startPoint.y;
                print (offsetX, offsetY)
                if ((target.width + offsetX) >= target.minimumWidth && offsetX != 0)
                {
                    target.width += offsetX;
                    target.x = fixedPont.x;
                }
                if ((target.height - offsetY) >= target.minimumHeight && offsetY != 0)
                {
                    target.height -= offsetY;
                    target.y += offsetY;
                }
            }
        }
    }

    MouseArea
    {
        id: area4
        x: 0
        y: 8
        width: 8
        height: target.height - 16
        hoverEnabled: true

        onEntered: cursorShape = Qt.SizeHorCursor;
        onExited: cursorShape = Qt.ArrowCursor;
        onPressed:
        {
            startPoint = Qt.point(mouseX, mouseY);
        }
        onPositionChanged:
        {
            if(pressed)
            {
                var offsetX = mouse.x - startPoint.x;
                if ((target.width - offsetX) >= target.minimumWidth)
                {
                    target.width -= offsetX;
                    target.x += offsetX;
                }
            }
        }
    }

    MoveMouseArea
    {
        id: area5
        x: 8
        y: 8
        width: area.target.width - 16
        height: area.target.height - 16
        target: area.target
    }

    MouseArea
    {
        id: area6
        x: target.width - 8
        y: 8
        width: 8
        height: target.height - 16
        hoverEnabled: true
        property real fixedX: 0;

        onEntered: cursorShape = Qt.SizeHorCursor;
        onExited: cursorShape = Qt.ArrowCursor;
        onPressed:
        {
            startPoint = Qt.point(mouseX, mouseY);
            fixedPont = Qt.point(target.x, target.y)
        }
        onPositionChanged:
        {
            if(pressed)
            {
                var offsetX = mouse.x - startPoint.x;
                if ((target.width + offsetX) >= target.minimumWidth && offsetX != 0)
                {
                    target.width += offsetX;
                    target.x = fixedPont.x;
                }
            }
        }
    }

    MouseArea
    {
        id: area7
        x: 0
        y: target.height - 8
        width: 8
        height: target.height - 16
        hoverEnabled: true
        property real fixedX: 0;

        onEntered: cursorShape = Qt.SizeBDiagCursor;
        onExited: cursorShape = Qt.ArrowCursor;
        onPressed:
        {
            startPoint = Qt.point(mouseX, mouseY);
            fixedPont = Qt.point(target.x, target.y)
        }
        onPositionChanged:
        {
            if (pressed)
            {
                var offsetX = mouse.x - startPoint.x;
                var offsetY = mouse.y - startPoint.y;
                if ((target.width - offsetX) >= target.minimumWidth && offsetX != 0)
                {
                    target.width -= offsetX;
                    target.x += offsetX;
                }
                if ((target.height + offsetY) >= target.minimumHeight && offsetY != 0)
                {
                    target.height += offsetY;
                    target.y = fixedPont.y;
                }
            }
        }
    }

    MouseArea
    {
        id: area8
        x: 8
        y: target.height - 8
        width: target.height - 16
        height: 8
        hoverEnabled: true
        property real fixedX: 0;

        onEntered: cursorShape = Qt.SizeVerCursor;
        onExited: cursorShape = Qt.ArrowCursor;
        onPressed:
        {
            startPoint = Qt.point(mouseX, mouseY);
            fixedPont = Qt.point(target.x, target.y)
        }
        onPositionChanged:
        {
            if (pressed)
            {
                var offsetY = mouse.y - startPoint.y;
                if ((target.height + offsetY) >= target.minimumHeight && offsetY != 0)
                {
                    target.height += offsetY;
                    target.y = fixedPont.y;
                }
            }
        }
    }

    MouseArea
    {
        id: area9
        x: target.width - 8
        y: target.height - 8
        width: 8
        height: 8
        hoverEnabled: true

        onEntered: cursorShape = Qt.SizeFDiagCursor;
        onExited: cursorShape = Qt.ArrowCursor
        onPressed:
        {
            startPoint = Qt.point(mouseX, mouseY);
            fixedPont = Qt.point(target.x, target.y)
        }
        onPositionChanged:
        {
            if(pressed)
            {
                var offsetX = mouse.x - startPoint.x;
                var offsetY = mouse.y - startPoint.y;
                if ((target.width + offsetX) >= target.minimumWidth && offsetX != 0)
                {
                    target.width += offsetX;
                    target.x = fixedPont.x;
                }
                if ((target.height + offsetY) >= target.minimumHeight && offsetY != 0)
                {
                    target.height += offsetY;
                    target.y = fixedPont.y;
                }
            }
        }
    }
}

        还有很多判断 minimum,maximum 什么的没有写全,但很简单,就不多展示了。

        其中的 MoveMouseArea 为:

import QtQuick 2.7

MouseArea
{
    hoverEnabled: true

    property var target: undefined;
    property point startPoint: Qt.point(0, 0);
    property point offsetPoint: Qt.point(0, 0);

    onPressed:
    {
        cursorShape = Qt.SizeAllCursor;
        startPoint = Qt.point(mouseX, mouseY);
    }
    onPositionChanged:
    {
        if(pressed)
        {
            offsetPoint = Qt.point(mouse.x - startPoint.x, mouse.y - startPoint.y);
            target.x = target.x + offsetPoint.x;
            target.y = target.y + offsetPoint.y;
        }
    }
    onReleased:
    {
        cursorShape = Qt.ArrowCursor;
    }
}

【结语】

        因为在其他地方并不需要拉伸操作,所以将区域 |5| 单独作为一个 qml 文件使用。

        还有一点关于 qml,闪烁严重的一部分原因是使用了 anchors 定位引起的,所以在窗口中的最底层的 item 使用坐标方式进行定位。其他 item 则不用。

        可以测试一下,还算可以,基本可以使用了,但仍然达不到 widget 那么流畅完美的程度。

  • 13
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦起丶

您的鼓励和支持是我创作最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值