1. 程式人生 > >QML實現的無邊框視窗的拉伸,拖拽,基本解決閃爍嚴重問題

QML實現的無邊框視窗的拉伸,拖拽,基本解決閃爍嚴重問題

使用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那麼流暢完美的程度。