1. 程式人生 > 其它 >QT: 如何移動和縮放一個無邊框視窗

QT: 如何移動和縮放一個無邊框視窗

一個QT視窗如下可以做到無邊框:

Window {
    id: window

    //Designer 竟然不支援..., 設計模式時要注意
    flags: Qt.FramelessWindowHint

    width: 500
    height: 300


    title: "Window Title"
}

不過要注意, 這樣QT Designer不支援, 在設計的時候可以先註釋掉, 最後在開啟.

一旦設定了FramelessWindowHint, 系統就不管你這個視窗的移動和縮放了, 就需要自己來處理了.

那怎麼處理哪, 大概有以下思路

  1. 增加一個接收拖動事件的元件, 讓它跟著滑鼠移動
  2. 增加一個縮放錨點, 隨著滑鼠縮放
  3. 增加視窗四周的滑鼠觸發區域, 可以隨著滑鼠向四個方向縮放 (此文沒包括實現) , 可以參考 https://evileg.com/en/post/280/{:target="_blank"}

我們先來看看如果拖動視窗, 程式碼如下:


/**
  頭部操作區域.
*/
Rectangle {
    id: titleOpRect
    x: 0
    y: 0
    width: parent.width
    height: 30

    property string title : "Hello Board"

    MouseArea {
        id: mouseMoveWindowArea
        //height: 20
        anchors.fill: parent
        
        acceptedButtons: Qt.LeftButton
        
        property point clickPos: "0,0"
        
        onPressed: {
            clickPos = Qt.point(mouse.x, mouse.y)
            //isMoveWindow = true
        }
        onReleased: {            
            //isMoveWindow = false
        }

        onPositionChanged: {
            var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
            
            //如果mainwindow繼承自QWidget,用setPos
            window.setX(window.x + delta.x)
            window.setY(window.y + delta.y)
        }
    }
    
    Button {
        id: closeButton
        
        width: 25
        height: parent.height
        text: "X"

        anchors.left: parent.left
        anchors.leftMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0


        flat: true
        font.bold: true
        font.pointSize: 14

        onClicked: {
            window.close()
        }
    }
    
    Text {
        id: titleText

        text: title
        anchors.bottom: parent.bottom

        //底部留點空間
        bottomPadding: 5

    } //end titleText



    
    Button {
        id: newStrikeButton
        
        width: 25
        height: parent.height
        text: "+"

        anchors.right: parent.right
        anchors.rightMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0

        flat: true
        font.pointSize: 22
    }

    Frame {
        width: titleOpRect.width
        height: 1
        anchors.bottom: titleOpRect.bottom
        Rectangle {
            height: parent.height
            width: parent.width
            color: "blue"
        }
    }
    
}

關鍵程式碼在MouseArea的onPressed 和 onPositionChanged 事件上. 比較容易.

我們再來看看如果縮放視窗

這次我們只是在視窗右下角放一個小矩形區域, 來捕獲滑鼠移動事件, 以實現縮放.


/**
  尾部操作區域.
*/
Rectangle {
    id: footOpRect
    anchors.bottom: parent.bottom
    width: parent.width
    height: 30


    //resize區域
    MouseArea {
        id: resize
        anchors {
            right: parent.right
            bottom: parent.bottom
        }
        width: 15
        height: 15
        cursorShape: Qt.SizeFDiagCursor

        property point clickPos: "1,1"

        //保持視窗左上角不動
        property int oldX
        property int oldY

        onPressed: {
            clickPos = Qt.point(mouse.x, mouse.y)
            //oldWidth = window.width
            //oldHeight = window.height
            oldX = window.x
            oldY = window.y
        }

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

            var minWidth = 100;
            var minHeight = 100;

            //最小
            var newWidth = (window.width + delta.x)<minWidth?minWidth:(window.width + delta.x);

            //最小
            var newHeight = (window.height + delta.y)<minHeight?minHeight:(window.height + delta.y);

            window.width = newWidth;
            window.height = newHeight;
            window.x = oldX
            window.y = oldY
        }

        onReleased: {
        }

        Rectangle {
            id: resizeHint
            color: "red"
            anchors.fill: resize
        }
    }
}

這段程式碼網上很常見,

  1. 不過這裡判斷了視窗的最小高度和寬度, 不會導致視窗太小看不見
  2. 滑鼠移動會導致負數, 所以這裡也做了判斷.
  3. 保持視窗左上角不動, 否則滑鼠跑來跑去有問題.

That's all, Thanks.

本文來自部落格園,作者:飛雲~,轉載請註明原文連結:https://www.cnblogs.com/cnscud/p/15020631.html