You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GTK子窗口首次启动未显示在父窗口上方的问题排查

问题解决:GTK偏好设置窗口首次打开不居中于父窗口

问题原因分析

  1. 标题设置错误:代码中误将偏好窗口的标题设置给了主窗口,导致偏好窗口标题未正确配置。
  2. 首次显示布局不同步:应用首次运行时,主窗口可能尚未完成屏幕映射与布局计算,此时显示子窗口,GTK无法准确获取父窗口位置来计算居中坐标;关闭再打开时,主窗口已完成初始化,位置计算逻辑能正常工作。

修复方案

关键修改点

  • 修正偏好窗口的标题设置目标
  • 显式指定子窗口居中于父窗口的位置策略
  • 移除冗余的窗口realize调用(gtk_window_present会自动处理该过程)

修改后的完整代码

#include <gtk/gtk.h>

void preferences_cb(GtkButton *button, gpointer data)
{
    GtkWidget *preferences = GTK_WIDGET(data);
    if (!preferences)
        return;

    // 强制子窗口基于父窗口居中
    gtk_window_set_position(GTK_WINDOW(preferences), GTK_WIN_POS_CENTER_ON_PARENT);
    gtk_window_present(GTK_WINDOW(preferences));
}

static void
activate (GtkApplication *app,
          gpointer        user_data)
{
  GtkWidget *window;
  GtkWidget *grid;
  GtkWidget *button; 
  GtkWidget *preferences;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), "parent window");
  gtk_widget_set_size_request(window, 700, 200);
  gtk_window_set_resizable (GTK_WINDOW(window), TRUE);

  grid = gtk_grid_new ();
  gtk_window_set_child ((GtkWindow *)window, grid);
  gtk_widget_set_vexpand(grid, TRUE);
  gtk_widget_set_hexpand(grid, TRUE);

  button = gtk_button_new_with_label("Show preferences.win..");
  gtk_grid_attach ((GtkGrid *)grid, button, 0, 0, 80, 22); 
  gtk_widget_set_vexpand(button, TRUE);
  gtk_widget_set_hexpand(button, TRUE);

  preferences = gtk_window_new();
  // 修正:将标题设置给偏好窗口而非主窗口
  gtk_window_set_title (GTK_WINDOW (preferences), "preferences");
  gtk_window_set_transient_for ((GtkWindow *)preferences, (GtkWindow *)window);
  gtk_window_set_default_size(GTK_WINDOW(preferences), 400, 500);
  gtk_window_set_hide_on_close (GTK_WINDOW(preferences), TRUE);
  gtk_window_set_resizable (GTK_WINDOW(preferences), FALSE);    

  g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(preferences_cb), preferences);
  gtk_window_present ((GtkWindow *)window);
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;
  #if GLIB_CHECK_VERSION(2, 74, 0)
      app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS); 
  #else
       app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE); 
  #endif
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}

代码说明

  1. 标题修正:将gtk_window_set_title的目标从主窗口window改为偏好窗口preferences,确保窗口标题正确显示。
  2. 居中策略:在打开偏好窗口的回调中添加gtk_window_set_position,强制GTK每次显示子窗口时都基于父窗口当前位置重新计算居中坐标,解决首次显示的布局不同步问题。
  3. 冗余代码移除:删除gtk_widget_realize(widget);,因为gtk_window_present会自动完成窗口的realize与映射流程。

内容的提问来源于stack exchange,提问作者dibyendu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:55:56