简体   繁体   English

当窗口管理器在 qt QML 中调整窗口大小时如何获得信号?

[英]How to get a signal when window manager is done resizing window in qt QML?

I'm trying to achieve a similar effect as iTunes' miniPlayer when resizing happens on macOS.在 macOS 上调整大小时,我试图实现与 iTunes 的 miniPlayer 类似的效果。 That is, detecting when a resizing of the the window has been completed, THEN changing the height to a certain value.也就是说,检测窗口的大小调整何时完成,然后将高度更改为某个值。 Here is a visual example :这是一个视觉示例:

在此处输入图片说明

The problem is that no signal in a QML window exists to notify me when the window manager is done resizing (that is, the user released the handle).问题是当窗口管理器完成调整大小(即用户释放句柄)时,QML 窗口中不存在通知我的信号。 Hence, if I don't have a signal and apply my height change as soon as width or height is changed during resizing, the window will flicker (double resize happens) as long as the user didn't release the handle.因此,如果我没有信号并在调整大小期间更改宽度或高度后立即应用我的高度更改,则只要用户没有释放手柄,窗口就会闪烁(发生双重调整大小)。

Thanks for any input or help!感谢您的任何输入或帮助!

You could implement your own resize handle pretty easily, using a MouseArea and handling the final resize calculation using onReleased (here forcing the height to be 75% of the width on release):您可以很容易地实现自己的调整大小句柄,使用 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
        }
    }
}

Here is an idea (that I did not try yet, but still):这是一个想法(我还没有尝试过,但仍然如此):

  1. Implement an event handler reacting to changes of the global cursor position.实现一个对全局光标位置变化做出反应的事件处理程序。 The cursor position inside the window is not applicable as the cursor is outside the window when grabbing a resize handle.窗口内的光标位置不适用,因为抓取调整大小手柄时光标位于窗口外。 Not sure if and how such an event handler is possible, but at least accessing the screen-global cursor position is possible in Qt .不确定这样的事件处理程序是否以及如何可能,但至少可以在 Qt 中访问屏幕全局光标位置。

  2. In the event handler, check if the vertical cursor position change compared to the last call of the handler is the same as the window height change.在事件处理程序中,检查与处理程序的最后一次调用相比的垂直光标位置变化是否与窗口高度变化相同。

    • If yes, assume that the user still holds the window resizing handle, so don't adapt window height.如果是,假设用户仍然持有窗口大小调整手柄,所以不要调整窗口高度。
    • If no, assume that the user released the window resizing handle and started to move the cursor around freely.如果不是,则假设用户释放了窗口大小调整手柄并开始自由移动光标。 Adapt the window height now.现在调整窗口高度。

You'll probably have to overcome several issues, such as (1) allowing for a certain divergence between the window height and cursor y position changes, as window height changes might be less frequent and trail the cursor movement somewhat, (2) engaging the cursor position event handler only during a window resize to limit system load.您可能需要克服几个问题,例如 (1) 允许窗口高度和光标 y 位置变化之间存在一定的差异,因为窗口高度变化可能不那么频繁并且在某种程度上跟踪光标移动,(2) 参与光标位置事件处理程序仅在窗口调整大小以限制系统负载期间。 But if it works, it's a native solution, not implementing own resizing handles.但如果它有效,它是一个本地解决方案,而不是实现自己的调整大小的句柄。

It seems you want QML to send two different signal types, one to mark the start and finish of resizing, and one to mark size changes during resizing.似乎您希望 QML 发送两种不同的信号类型,一种用于标记调整大小的开始和结束,另一种用于标记调整大小期间的大小变化。 The event sequence would then be something like this:事件序列将是这样的:

window.resizeStarted() // hypothetical new event

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

window.resizeEnded()   // hypothetical new event

That is apparently impossible in Qt out of the box, but you should be able to implement it yourself with this approach, originally meant to not repaint the window at all while resizing:这在 Qt 中显然是不可能的,但是您应该能够使用这种方法自己实现它,最初的目的是在调整大小时根本不重新绘制窗口:

Filter the relevant events out until the mouse button has been released.过滤掉相关事件,直到释放鼠标按钮。 Specifically, "eat" the resize event while the mouse button is held down, and then synthesize the final resize event once the mouse is released.具体来说,就是在按住鼠标按钮的同时“吃掉”resize 事件,然后在释放鼠标后合成最终的resize 事件。 You can do it all in an event filter attached to the window / widget object that displays your QML interface.您可以在附加到显示 QML 界面的窗口/小部件对象的事件过滤器中完成所有操作。 ( source ) 来源

The process would be very similar to the one in the quote:该过程与引用中的过程非常相似:

  1. Extend the QML Window type with custom signals:使用自定义信号扩展 QML 窗口类型:

     //MyWindow.qml Window { signal resizeStarted() signal resizeEnded() }
  2. Create an event filter on the QML window that "eats" all window resize events.在 QML 窗口上创建一个“吃掉”所有窗口大小调整事件的事件过滤器。 When it encounters the first one, it sends resizeStarted() .当它遇到第一个时,它发送resizeStarted() Then it forwards the window resize events.然后它转发窗口调整大小事件。 When it encounters a mouse release event while resizing, it sends resizeEnded() after the last widthChanged() / heightChanged() event.当它在调整大小时遇到​​鼠标释放事件,它会在最后一个widthChanged() / heightChanged()事件之后发送resizeEnded()

  3. Implement a corresponding signal handler onResizeEnded in QML to react, here to adapt the height of your application window to a certain fixed value.在 QML 中实现一个对应的信号处理程序onResizeEnded来反应,这里是为了让你的应用程序窗口的高度适应某个固定值。

Seems quite a promising route to me, but to note, I haven't tried it in code so far.对我来说似乎是一条很有前途的路线,但请注意,到目前为止我还没有在代码中尝试过。

QML provided some NOTIFY signals when property values are supposed to be updated.当应该更新属性值时,QML 提供了一些 NOTIFY 信号。 So you can use Window.width 's and Window.height 's:所以你可以使用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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM