如何从G_DEFINE_TYPE声明的自定义类型中获取GtkWindow或顶级部件?
问题:从G_DEFINE_TYPE声明的自定义类型中获取GtkWindow/顶级部件
我需要从使用G_DEFINE_TYPE声明的自定义类型中获取GtkWindow或顶级部件,以下是我的代码实现:
MyAppWindow.c
#include "MyAppWindow.h" struct _MyAppWindow { GtkApplicationWindow parent; }; G_DEFINE_TYPE (MyAppWindow, my_app_window, GTK_TYPE_APPLICATION_WINDOW); void my_app_window_init (MyAppWindow *app) { } void my_app_window_class_init (MyAppWindowClass *class) { } MyAppWindow * my_app_window_new (MyApp *app) { return g_object_new (MY_APP_WINDOW_TYPE, "application", app, NULL); }
MyAppWindow.h
#ifndef _MY_APP_WINDOW_H_INCLUDED #define _MY_APP_WINDOW_H_INCLUDED #include "MyApp.h" #define MY_APP_WINDOW_TYPE (my_app_window_get_type ()) G_DECLARE_FINAL_TYPE (MyAppWindow, my_app_window, MY, APP_WINDOW, GtkApplicationWindow) MyAppWindow * my_app_window_new (MyApp *); #endif
MyApp.c
struct _MyApp { GtkApplication parent; }; G_DEFINE_TYPE (MyApp, my_app, GTK_TYPE_APPLICATION); void my_app_init (MyApp *app) { } void my_app_activate (GApplication *app) { MyAppWindow *win; // 创建窗口: win = my_app_window_new (MY_APP (app)); } void my_app_class_init (MyAppClass *class) { G_APPLICATION_CLASS (class)->activate = my_app_activate; } MyApp *my_app_new (AppData *pad) { MyApp *obj = g_object_new (MY_APP_TYPE, "application-id", PROJECT_APPID, "flags", G_APPLICATION_DEFAULT_FLAGS, NULL); return obj; }
activate函数补充实现
void my_app_activate (GApplication *app) { MyAppWindow *win = my_app_window_new (MY_APP (app)); // .. 更多代码 g_action_map_add_action_entries (G_ACTION_MAP (app), entries, G_N_ELEMENTS (entries), app); }
回调函数cb_showmsg
void cb_showmsg (GSimpleAction *action, GVariant *parameter, gpointer user_data) { // user_data: 需要同时访问GApplication和MyAppWindow // 用户Holger提供的一种方案: GtkWindow* toplevel = gtk_application_get_active_window (user_data); // }
我需要获取MyAppWindow来显示或隐藏顶级窗口,请问有什么可行的解决思路?
可行解决思路
类型转换直接获取:因为
MyAppWindow是GtkApplicationWindow的子类,而GtkApplicationWindow本身就是GtkWindow的子类,可直接用类型宏转换。注意先做类型检查避免错误:void cb_showmsg (GSimpleAction *action, GVariant *parameter, gpointer user_data) { GtkWindow* toplevel = gtk_application_get_active_window (GTK_APPLICATION(user_data)); if (GTK_IS_APPLICATION_WINDOW(toplevel) && MY_IS_APP_WINDOW(toplevel)) { MyAppWindow *win = MY_APP_WINDOW(toplevel); // 执行显示/隐藏操作,如gtk_widget_show(GTK_WIDGET(win))或gtk_widget_hide(GTK_WIDGET(win)) } }保存窗口引用到App实例:在
MyApp结构体中添加成员存储窗口指针,后续通过App实例直接获取:- 修改
MyApp结构体(需在头文件声明):struct _MyApp { GtkApplication parent; MyAppWindow *window; // 新增窗口成员 }; - 在
my_app_activate中赋值:void my_app_activate (GApplication *app) { MyApp *my_app = MY_APP(app); my_app->window = my_app_window_new (my_app); gtk_widget_show(GTK_WIDGET(my_app->window)); // 显示窗口 g_action_map_add_action_entries (G_ACTION_MAP (app), entries, G_N_ELEMENTS (entries), app); } - 在回调中直接调用:
void cb_showmsg (GSimpleAction *action, GVariant *parameter, gpointer user_data) { MyApp *my_app = MY_APP(user_data); if (my_app->window != NULL) { gtk_widget_hide(GTK_WIDGET(my_app->window)); // 示例:隐藏窗口 } }
- 修改
封装结构体作为user_data传递:如果需要同时访问App和窗口,可封装一个结构体作为回调的
user_data:- 定义结构体:
typedef struct { MyApp *app; MyAppWindow *window; } CallbackData; - 在
my_app_activate中创建并传递:void my_app_activate (GApplication *app) { MyAppWindow *win = my_app_window_new (MY_APP(app)); CallbackData *data = g_new(CallbackData, 1); data->app = MY_APP(app); data->window = win; g_action_map_add_action_entries (G_ACTION_MAP (app), entries, G_N_ELEMENTS (entries), data); // 记得在App退出时释放data,例如在my_app_shutdown函数中处理 } - 在回调中使用:
void cb_showmsg (GSimpleAction *action, GVariant *parameter, gpointer user_data) { CallbackData *data = user_data; if (data->window != NULL) { gtk_widget_show(GTK_WIDGET(data->window)); // 示例:显示窗口 } }
- 定义结构体:
内容的提问来源于stack exchange,提问作者Joel
相关产品推荐
相关产品推荐

