使用QML保存窗口状态

Tim*_*mmm 5 settings qt window qml qtquick2

有没有一种很好的方法来记录QtQuick应用程序的窗口状态?该文档提供了以下方法:

Settings {
    property alias x: mainWindow.x
    property alias y: mainWindow.y
    property alias width: mainWindow.width
    property alias height: mainWindow.height
Run Code Online (Sandbox Code Playgroud)

然而,这有三个缺陷:

  1. 当您调整窗口大小/移动窗口时,它会连续写入设置文件.
  2. 它不记得窗口是否最大化(Notepad ++也受到这个恼人的缺陷btw).
  3. 如果最大化窗口,则不会保存未最大化的几何体.

有没有人有更好的代码?

Tim*_*mmm 2

据我有限的测试显示,我设法做出了一些效果很好的东西。我确实必须做一个 hacky 位,这是因为不幸的Window.visibility是在之后更新Window.x/y/width/height,这意味着如果您尝试记录窗口几何图形,您不能只检查Window.visibilityin的状态onXChanged。相反,我必须记录前两个值,然后在窗口最大化时丢弃最新的值。

编辑:这并不是很完美。如果最大化窗口,则关闭应用程序。然后打开它,然后再次关闭它。然后再次打开它,当您取消最大化时,它不会返回到正确的窗口大小。我认为修复这个问题将是非常丑陋的 QML,我可能会在它真正所属的 C++ 中实现它。

import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.3
import Qt.labs.settings 1.0

Item {
    property Window window

    // Default properties for the application's first run.
    property int defaultX: 100
    property int defaultY: 100
    property int defaultWidth: 500
    property int defaultHeight: 500
    property bool defaultMaximised: false

    Settings {
        id: windowStateSettings
        category: "WindowState"
        property int x
        property int y
        property int width
        property int height
        property bool maximised
    }

    Component.onCompleted: {
        if (windowStateSettings.width === 0 || windowStateSettings.height === 0)
        {
            // First run, or width/height are screwed up.
            curX = defaultX;
            curY = defaultY;
            curWidth = defaultWidth;
            curHeight = defaultHeight;
            curMaximised = defaultMaximised
        }
        else
        {
            curX = windowStateSettings.x;
            curY = windowStateSettings.y;
            curWidth = windowStateSettings.width;
            curHeight = windowStateSettings.height;
            curMaximised = windowStateSettings.maximised
        }
        window.x = prevX = curX;
        window.y = prevY = curY;
        window.width = prevWidth = curWidth;
        window.height = prevHeight = curHeight;

        if (curMaximised)
            window.visibility = Window.Maximized;
    }

    // Remember the windowed geometry, and whether it is maximised or not.
    // Internal use only.
    property int curX
    property int curY
    property int curWidth
    property int curHeight
    property bool curMaximised

    // We also have to save the previous values of X/Y/Width/Height so they can be restored if we maximise, since we
    // can't tell that the updated X,Y values are because of maximisation until *after* the maximisation.
    property int prevX
    property int prevY
    property int prevWidth
    property int prevHeight

    Connections {
        target: window
        onVisibilityChanged: {
            if (window.visibility === Window.Maximized)
            {
                curMaximised = true;
                // Ignore the latest X/Y/width/height values.
                curX = prevX;
                curY = prevY;
                curWidth = prevWidth;
                curHeight = prevHeight;
            }
            else if (window.visibility === Window.Windowed)
            {
                curMaximised = false;
            }
            else if (window.visibility === Window.Hidden)
            {
                // Save settings.
                windowStateSettings.x = curX;
                windowStateSettings.y = curY;
                windowStateSettings.width = curWidth;
                windowStateSettings.height = curHeight;
                windowStateSettings.maximised = curMaximised;
            }
        }

        // We can't use window.visibility here to ignore the maximised geometry because it changes after the geometry.
        // Instead we cache the two previous values and revert them if maximised.
        onXChanged: {
            prevX = curX;
            curX = window.x;
        }
        onYChanged: {
            prevY = curY;
            curY = window.y;
        }
        onWidthChanged: {
            prevWidth = curWidth;
            curWidth = window.width;
        }
        onHeightChanged: {
            prevHeight = curHeight;
            curHeight = window.height;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

ApplicationWindow {
    id: mainWindow

    WindowStateSaver {
        window: mainWindow
        defaultWidth: 1000 // Or whatever. You can also specify the defaultX/Y if you want.
        defaultHeight: 700
    }
Run Code Online (Sandbox Code Playgroud)