在窗口管理器完成qt QML中的窗口大小调整后,如何获取信号?

时间:2019-05-22 08:55:41

标签: c++ qt resize qml window

在macOS上调整大小时,我正在尝试实现与iTunes miniPlayer类似的效果。即,检测窗口的尺寸调整何时完成,然后将高度调整为一定宽度。这是一个视觉示例:

enter image description here

问题在于,当窗口管理器完成大小调整(即用户释放了句柄)时,QML窗口中没有信号通知我。因此,如果我没有信号并在更改宽度或高度后立即应用它,只要用户不松开手柄,窗口就会闪烁(发生两次调整大小)。

感谢您的任何输入或帮助!

4 个答案:

答案 0 :(得分:0)

您可以使用MouseArea轻松实现自己的调整大小手柄,并使用onReleased处理最终的调整大小计算(此处将高度强制为释放时宽度的75%):

Window {
    id: window
    flags: Qt.FramelessWindowHint
    visible: true
    height: 300
    width: 400

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

        property point clickPos: "1,1"

        onPressed: {
            resize.clickPos  = Qt.point(mouse.x,mouse.y)
        }

        onPositionChanged: {
            var delta = Qt.point(mouse.x-resize.clickPos.x, mouse.y-resize.clickPos.y)
            window.width += delta.x;
            window.height += delta.y;
        }

        onReleased: {
            window.height = .75 * window.width
        }

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

答案 1 :(得分:0)

当属性值应该更新时,QML提供了一些NOTIFY信号。因此,您可以使用Window.widthWindow.height

Window {
    id: window

    onWidthChanged: {
        // Will be executed after window.width value changes.
    }

    onHeightChanged: {
        // Will be executed after window.height value changes.
    }

    // Other window-related stuff
}

答案 2 :(得分:0)

这是一个主意(我还没有尝试,但是仍然尝试过):

  1. 实现对全局光标位置的更改作出反应的事件处理程序。抓取调整大小手柄时,光标在窗口内的位置不适用,因为光标在窗口外。不知道这种事件处理程序是否可行以及如何可行,但是至少要访问屏幕全局光标位置是possible in Qt

  2. 在事件处理程序中,检查与处理程序的最后一次调用相比,垂直光标位置的更改是否与窗口高度更改相同。

    • 如果是,请假设用户仍然握住窗口大小调整手柄,所以不要调整窗口高度。
    • 如果否,则假定用户释放了窗口大小调整手柄并开始自由移动光标。立即调整窗口高度。

您可能必须克服几个问题,例如(1)允许窗口高度和光标y位置更改之间存在一定差异,因为窗口高度更改可能不那么频繁并且在一定程度上落后于光标移动,(2 )仅在调整窗口大小以限制系统负载时才使用光标位置事件处理程序。但是,如果可行,那就是本机解决方案,而不是实现自己的调整大小句柄。

答案 3 :(得分:0)

似乎您希望QML发送两种不同的信号类型,一种用于标记调整大小的开始和结束,一种用于标记调整大小期间的大小变化。事件序列将如下所示:

window.resizeStarted() // hypothetical new event

window.widthChanged()
window.heightChanged()
window.widthChanged()
window.heightChanged()
...

window.resizeEnded()   // hypothetical new event

在Qt中开箱即用显然是不可能的,但是您应该可以使用这种方法自己实现它,最初的目的是在调整大小时根本不重新绘制窗口:

过滤掉相关事件,直到释放鼠标按钮。具体来说,在按住鼠标按钮的同时“吃掉”调整大小事件,然后在释放鼠标后合成最终的调整大小事件。您可以在附加到显示QML界面的window / widget对象的事件过滤器中完成所有操作。 (source

该过程与引用中的过程非常相似:

  1. 使用自定义信号扩展QML窗口类型:

    //MyWindow.qml
    Window {
       signal resizeStarted()
       signal resizeEnded()
    }
    
  2. 在QML窗口上创建事件过滤器,以“吃掉”所有窗口大小调整事件。当遇到第一个时,它将发送resizeStarted()。然后,它转发窗口调整大小事件。在调整大小时遇到​​鼠标释放事件时,它将在最后一个resizeEnded() / widthChanged()事件之后发送heightChanged()

  3. 在QML中实施相应的信号处理程序onResizeEnded进行响应,此处将您的应用程序窗口的高度调整为某个固定值。

对我来说似乎是一条很有前途的途径,但是要注意,到目前为止,我还没有在代码中尝试过。