【问题标题】:How can I resize frameless window in QML?如何在 QML 中调整无框窗口的大小?
【发布时间】:2022-10-23 18:25:48
【问题描述】:

如何在无框窗口中返回调整边框大小的逻辑?

框架窗口具有以下逻辑:

QML 中的代码:

import QtQuick
import QtQuick.Controls 2.5
import Qt5Compat.GraphicalEffects
import NR 1.0

Window {
    id: mainWindow
    width: 640
    height: 720
    visible: true
    title: qsTr("Hello World")
    flags: Qt.Window | Qt.FramelessWindowHint
    color: "transparent"

    // (1)

    MouseArea {
        id: bottomArea
        height: 5
        anchors {
            bottom: parent.bottom
            left: parent.left
            right: parent.right
        }
        cursorShape: Qt.SizeVerCursor

        onPressed: {
            previousY = mouseY
        }

        onMouseYChanged: {
            var dy = mouseY - previousY
            mainWindow.setHeight(mainWindow.height + dy)
        }
    }
    // Some code of another Items here
}

我在左侧尝试了这段代码:

 MouseArea {
        id: leftSideMouseArea
        anchors.fill: parent
        property point lastMousePos: Qt.point(0, 0)
        onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
        onMouseXChanged: mainWindow.width += (mouseX + lastMousePos.x)
    }

我将此代码放在 (1) 位置,但它不起作用 - 单击(不移动)窗口调整为正确大小并且应用程序崩溃并出现错误:

QQuickPaintedItem::textureProvider: 只能在 暴露窗口的渲染线程

这看起来像图片:

你能帮助我吗?

谢谢!

【问题讨论】:

    标签: c++ qt qml c++17 qt6


    【解决方案1】:

    我想不出更好的方法来做到这一点

    这是一个工作示例:

    import QtQuick 2.15
    import QtQuick.Window 2.15
    
    Window {
        id: window
        width: 640
        height: 480
        visible: true
        title: qsTr("Hello World")
        flags: Qt.Window | Qt.FramelessWindowHint
    
        Rectangle
        {
            id: dragItemRight
            anchors.top: parent.top
            anchors.bottom: parent.bottom
            width: 5
            color: "red"
            x: window.width - width
    
            onXChanged:
            {
                if (dragItemRightMouse.drag.active)
                {
                    window.width = dragItemRight.x + width
                }
            }
    
            MouseArea
            {
                id: dragItemRightMouse
                anchors.fill: parent
                drag.target: parent
                drag.axis: Drag.XAxis
                cursorShape: Qt.SizeHorCursor
                drag.minimumX: 300
    
                drag.onActiveChanged:
                {
                    if (!drag.active)
                    {
                        dragItemRight.x = Qt.binding(function() { return window.width - width })
                    }
                }
            }
        }
    
        Rectangle
        {
            id: dragItemBottom
            anchors.left: parent.left
            anchors.right: parent.right
            height: 5
            color: "red"
            y: window.height - height
    
            onYChanged:
            {
                if (dragItemBottomMouse.drag.active)
                {
                    window.height = dragItemBottom.y + height
                }
            }
    
            MouseArea
            {
                id: dragItemBottomMouse
                anchors.fill: parent
                drag.target: parent
                drag.axis: Drag.YAxis
                cursorShape: Qt.SizeVerCursor
                drag.minimumY: 300
    
                drag.onActiveChanged:
                {
                    if (!drag.active)
                    {
                        dragItemBottom.y = Qt.binding(function() { return window.height - height })
                    }
                }
            }
        }
    
        Rectangle
        {
            id: dragItemBottomRight
            width: 5
            height: 5
            color: "green"
            x: window.width - width
            y: window.height - height
    
            onYChanged:
            {
                if (dragItemBottomRightMouse.drag.active)
                {
                    window.height = dragItemBottomRight.y + height
                }
            }
            onXChanged:
            {
                if (dragItemBottomRightMouse.drag.active)
                {
                    window.width = dragItemBottomRight.x + width
                }
            }
    
            MouseArea
            {
                id: dragItemBottomRightMouse
                anchors.fill: parent
                drag.target: parent
                drag.axis: Drag.XAndYAxis
                drag.minimumX: 300
                drag.minimumY: 300
                cursorShape: Qt.SizeFDiagCursor
    
                drag.onActiveChanged:
                {
                    if (!drag.active)
                    {
                        dragItemBottomRight.x = Qt.binding(function() { return window.width - width })
                        dragItemBottomRight.y = Qt.binding(function() { return window.height - height })
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我找到了解决方案:

      import QtQuick
      import QtQuick.Controls 2.15
      import Qt5Compat.GraphicalEffects
      import NR 1.0
      
      Window {
          id: mainWindow
          width: 640
          height: 720
          visible: true
          title: qsTr("Hello World")
          flags: Qt.Window | Qt.FramelessWindowHint
          color: "transparent"
      
          property point startMousePos
          property point startWindowPos
          property size startWindowSize
      
          function absoluteMousePos(mouseArea) {
              var windowAbs = mouseArea.mapToItem(null, mouseArea.mouseX, mouseArea.mouseY)
              return Qt.point(windowAbs.x + mainWindow.x,
                              windowAbs.y + mainWindow.y)
          }
      
          
      
          MouseArea {
              id: moveArea
              anchors.fill: title
              property point mPos;
              onPressed: {
                  mPos = Qt.point(mouseX, mouseY)
              }
              onPositionChanged: {
                  mainWindow.setX(mainWindow.x + mouseX - mPos.x)
                  mainWindow.setY(mainWindow.y + mouseY - mPos.y)
              }
          }
      
          MouseArea {
              id: leftArea
              anchors.top: parent.top
              anchors.topMargin: 48
              anchors.bottom: parent.bottom
              anchors.bottomMargin: 5
              cursorShape: Qt.SizeHorCursor
              width: 5
              onPressed: {
                  startMousePos = absoluteMousePos(leftArea)
                  startWindowPos = Qt.point(mainWindow.x, mainWindow.y)
                  startWindowSize = Qt.size(mainWindow.width, mainWindow.height)
              }
              onMouseXChanged: {
                  var abs = absoluteMousePos(leftArea)
                  var newWidth = Math.max(mainWindow.minimumWidth, startWindowSize.width - (abs.x - startMousePos.x))
                  var newX = startWindowPos.x - (newWidth - startWindowSize.width)
                  mainWindow.x = newX
                  mainWindow.width = newWidth
              }
      
              Rectangle {
                  anchors.fill: parent
                  color: "red"
              }
          }
      
          MouseArea {
              id: rightArea
              width: 5
              x: parent.width - rightArea.width
              anchors.right: parent.rigth
              anchors.top: parent.top
              anchors.rightMargin: 5
              anchors.topMargin: 48
              anchors.bottom: parent.bottom
              anchors.bottomMargin: 5
              cursorShape: Qt.SizeHorCursor
      
              onPressed: {
                  startMousePos = absoluteMousePos(rightArea)
                  startWindowPos = Qt.point(mainWindow.x, mainWindow.y)
                  startWindowSize = Qt.size(mainWindow.width, mainWindow.height)
              }
              onMouseXChanged: {
                  var abs = absoluteMousePos(rightArea)
                  var newWidth = Math.max(mainWindow.minimumWidth, startWindowSize.width + (abs.x - startMousePos.x))
                  mainWindow.width = newWidth
              }
      
              Rectangle {
                  anchors.fill: parent
                  color: "red"
              }
          }
      
          MouseArea {
              id: buttonArea
              y: parent.height - buttonArea.height
              height: 5
              anchors.leftMargin: 5
              anchors.left: parent.left
              anchors.rightMargin: 5
              anchors.right: parent.right
              anchors.bottom: parent.bottom
              cursorShape: Qt.SizeVerCursor
      
              onPressed: {
                  startMousePos = absoluteMousePos(buttonArea)
                  startWindowPos = Qt.point(mainWindow.x, mainWindow.y)
                  startWindowSize = Qt.size(mainWindow.width, mainWindow.height)
              }
              onMouseYChanged: {
                  var abs = absoluteMousePos(buttonArea)
                  var newHeight = Math.max(mainWindow.minimumHeight, startWindowSize.height + (abs.y - startMousePos.y))
                  mainWindow.height = newHeight
              }
      
              Rectangle {
                  anchors.fill: parent
                  color: "red"
              }
          }
      
      }
      

      【讨论】:

        【解决方案3】:

        Qt5.15 开始,我们有了startSystemResize,它执行原生调整大小,建议不要使用类似的方法将点击位置与当前位置进行比较.

        功能很简单;一旦你经过一个角落,窗口就会开始调整大小。

        无框窗口的示例如下所示:

        自定义窗口.QML

        使用此属性更改可以按下鼠标的窗口边缘的偏移量。
        propertyintedgeOffest:5

        也用于移动窗口您可以使用DragHandler,它在激活时调用startSystemMove

        Window {
            width: 200; height: 100
            color: '#fab'
            flags: Qt.Window | Qt.FramelessWindowHint
        
            DragHandler {
                onActiveChanged: if(active) startSystemMove();
            }
        
            MouseArea {
                id: mouseArea
                anchors.fill: parent
                hoverEnabled: true
                acceptedButtons: Qt.LeftButton
        
                property int edges: 0;
                property int edgeOffest: 5;
        
                function setEdges(x, y) {
                    edges = 0;
                    if(x < edgeOffest) edges |= Qt.LeftEdge;
                    if(x > (width - edgeOffest))  edges |= Qt.RightEdge;
                    if(y < edgeOffest) edges |= Qt.TopEdge;
                    if(y > (height - edgeOffest)) edges |= Qt.BottomEdge;
                }
        
                cursorShape: {
                    return !containsMouse ? Qt.ArrowCursor:
                           edges == 3 || edges == 12 ? Qt.SizeFDiagCursor :
                           edges == 5 || edges == 10 ? Qt.SizeBDiagCursor :
                           edges & 9 ? Qt.SizeVerCursor :
                           edges & 6 ? Qt.SizeHorCursor : Qt.ArrowCursor;
                }
        
                onPositionChanged: setEdges(mouseX, mouseY);
                onPressed: {
                    setEdges(mouseX, mouseY);
                    if(edges && containsMouse) {
                        startSystemResize(edges);
                    }
                }
            }
        }
        

        最后的笔记

        尽管如此,我还是不建议您开发具有自定义功能的自定义窗口,这会迫使您处理很多功能,同时仍然感觉不像原生功能。

        但是,有一些 github 项目为此提供了一些帮助程序库,因此请查看这些项目。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-08-29
          • 2013-07-12
          • 2011-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-16
          相关资源
          最近更新 更多