GTK子窗口首次启动未显示在父窗口上方的问题排查
问题解决:GTK偏好设置窗口首次打开不居中于父窗口
问题原因分析
- 标题设置错误:代码中误将偏好窗口的标题设置给了主窗口,导致偏好窗口标题未正确配置。
- 首次显示布局不同步:应用首次运行时,主窗口可能尚未完成屏幕映射与布局计算,此时显示子窗口,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; }
代码说明
- 标题修正:将
gtk_window_set_title的目标从主窗口window改为偏好窗口preferences,确保窗口标题正确显示。 - 居中策略:在打开偏好窗口的回调中添加
gtk_window_set_position,强制GTK每次显示子窗口时都基于父窗口当前位置重新计算居中坐标,解决首次显示的布局不同步问题。 - 冗余代码移除:删除
gtk_widget_realize(widget);,因为gtk_window_present会自动完成窗口的realize与映射流程。
内容的提问来源于stack exchange,提问作者dibyendu
相关产品推荐
相关产品推荐

