保存和加载窗口状态

用例

在会话之间保存和恢复窗口状态是某些应用程序的一个有用特性。

由于应用程序最了解它们的状态和几何形状——以及应用程序启动后是否应该应用这些状态和几何形状,以及如何应用——因此最好将此功能放在创建应用程序窗口的代码附近。

状态应该存储在哪里

有两种选择来存储窗口状态

  • 位于 $XDG_CACHE_HOME/your.application.id (或在 Flatpak 应用程序内部运行时,简单地 $XDG_CACHE_HOME) 的文件

  • GSettings

两种选择都有其自身的优点和权衡。

第一种选择要求您编写序列化和反序列化代码,但它具有可移植性,并且不需要在运行时存在辅助文件,例如 GSettings 模式。这意味着您需要编写更多的代码,但它允许,例如,以未安装的方式运行您的应用程序。

第二种选择为您提供序列化和反序列化代码,但它要求您定义设置键模式并在已知位置安装它。这意味着您将使您的代码保持最小,但它也将需要安装。

通常情况下,在其他条件相同的情况下,最好使用 GSettings 而不是自定义文件。GSettings API 更好、更可靠、更快。

应该保存哪种状态?

通常应该保存的窗口状态很少

  • 窗口大小

  • 如果窗口支持,窗口是否最大化

  • 如果窗口支持,窗口是否全屏

窗口位置最好交给窗口管理器。可以使用相同的方法保存其他状态,因此将它们作为练习留给读者。

提示

如果您的应用程序使用 GtkPaned 组件,您可能还想通过跟踪 GtkPaned:position 属性来保存手柄的位置。

窗口几何形状应该通过获取来自 GtkWindow:default-widthGtkWindow:default-height 属性的通知来更新;窗口状态,例如“最大化”和“全屏”,也映射到 GtkWindow 属性。

将状态保存和恢复到 GSettings

首先,您需要一个 GSettings 模式,以定义键、值的类型以及每个键的默认值

<schemalist>
  <schema id="com.example.YourApp.State" path="/com/example/YourApp/State/">
    <key name="width" type="i">
      <default>640</default>
    </key>
    <key name="height" type="i">
      <default>480</default>
    </key>
    <key name="is-maximized" type="b">
      <default>false</default>
    </key>
    <key name="is-fullscreen" type="b">
      <default>false</default>
    </key>
  </schema>
</schemalist>

一旦您有了模式,就可以将窗口属性映射到该模式定义的 GSettings 键

static void
my_application_window_init (MyApplicationWindow *self)
{
  GSettings *settings = g_settings_new ("com.example.YourApp.State");

  // update the settings when the properties change and vice versa
  g_settings_bind (settings, "width",
                   self, "default-width",
                   G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (settings, "height",
                   self, "default-height",
                    G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (settings, "is-maximized",
                   self, "maximized",
                   G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (settings, "is-fullscreen",
                   self, "fullscreened",
                   G_SETTINGS_BIND_DEFAULT);
}

上面的代码将自动将属性设置为相应 GSettings 键中的值,并在属性发生更改时使用属性的值更新 GSettings 键。