信号在插入的飞行小部件中不起作用
Signals doesnt work in inserted on fly widgets
我有一个自定义小部件,例如按钮,它具有下一个结构
GtkWidget* button_new(ServerEntity *server)
{
GtkWidget *fixed;
GtkWidget *favoriteEventBox;
GtkWidget *eventBox;
fixed= gtk_fixed_new();
eventBox = gtk_event_box_new();
favoriteEventBox = gtk_event_box_new();
gtk_fixed_put(GTK_FIXED(fixed), eventBox, 0,0);
gtk_fixed_put(GTK_FIXED(fixed), favoriteEventBox, 183,8);
g_signal_connect (G_OBJECT (eventBox),
"button_press_event",
G_CALLBACK (on_event_box_button_press),
server);
g_signal_connect (G_OBJECT (favoriteEventBox),
"button_press_event",
G_CALLBACK (on_favorite_box_button_press),
server);
g_signal_connect (G_OBJECT (fixed),
"draw",
G_CALLBACK (on_fixed_draw),
server);
return fixed;
}
我把它放到vbox里,然后放到scrollable里window:
GtkWidget *scroll_window;
scroll_window = gtk_scrolled_window_new(NULL, NULL);
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll_window), box);
return scroll_window;
box 在 c 文件中仍然可见,稍后我用它来动态添加小部件。主机小部件是单一的,所以我可以做到。
然后我把它放入gtk_fixed、gtk_fixed和window
当我在所有小部件构建过程中添加我的自定义按钮时,它会在两个嵌套框上收到按钮按下和绘制信号。但是当我稍后添加按钮时,只有当我拉动滚动条时才会调用绘制信号。
这就是我在构造和执行期间添加按钮的方式。
void server_list_set_servers(SERVER_ENTITY_CONTAINER* servers)
{
int servers_count = server_entity_container_get_items_count(servers);
int j = 0;
int i = 0;
for (i = 0; i < servers_count; i++)
{
GtkWidget* button;
ServerEntity* server = server_entity_container_get_item_at(servers, i);
button = button_new(server);
// gtk_table_attach_defaults (GTK_TABLE (table), button, j, j + 1, i, i + 1);
gtk_box_pack_end(GTK_BOX(box), button, TRUE, TRUE, 5);
gtk_widget_show (button);
}
}
并且在构建期间按钮仍然接收所有信号,但在它旁边,即时添加 - 没有。
尝试将 "event" 信号连接到所有设备,已删除 scrollable_window,将框更改为 table - 不起作用。为什么会这样?
主循环启动后,GTK 系统无法将委托函数连接到信号。
因此,将整个视图重新创建为 window 是一个很好的做法。
在我的例子中,我从登录 GtkWindow 的用户那里获取凭据,调用 gtk_quit,向服务器发出两次请求 - 首先验证凭据,然后获取数据,然后才创建包含所有数据的 Main GtkWindow手,并根据需要用任意数量的按钮填充它。
我不明白你说的一半,所以也许我没有理解你真正的问题,但我知道你可以动态更改 GUI,连接或不连接信号,没有任何问题。
#include <gtk/gtk.h>
static void
child_button(GtkButton *button)
{
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"A child button has been clicked");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
static void
main_button(GtkButton *button, GtkContainer *vbox)
{
GtkWidget *widget = gtk_button_new_with_label("New button");
g_signal_connect(widget, "clicked", G_CALLBACK(child_button), NULL);
gtk_container_add(vbox, widget);
gtk_widget_show(widget);
}
int main(int argc, char **argv)
{
GtkWidget *window, *vbox, *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_container_add(GTK_CONTAINER(window), vbox);
button = gtk_button_new_with_label("Add button");
g_signal_connect(button, "clicked", G_CALLBACK(main_button), vbox);
gtk_container_add(GTK_CONTAINER(vbox), button);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
您也可以准备小部件(连接或未连接到信号)并稍后添加,只需重新排列上面代码段中的代码即可。信号毕竟只是 C 回调。
附录
我更新了上面的代码以使用 GtkEventBox
和 button-press-event
信号只是为了表明改变小部件或信号不会改变最终结果。
#include <gtk/gtk.h>
static gboolean
child_event_box(GtkEventBox *event_box)
{
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"A button has been pressed inside a child event box");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return FALSE;
}
static gboolean
main_event_box(GtkEventBox *event_box, GdkEvent *event, GtkContainer *vbox)
{
GtkWidget *label = gtk_label_new("Dynamic event box");
GtkWidget *widget = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(widget), label);
g_signal_connect(widget, "button-press-event", G_CALLBACK(child_event_box), NULL);
gtk_container_add(vbox, widget);
gtk_widget_show_all(widget);
return FALSE;
}
int main(int argc, char **argv)
{
GtkWidget *window, *vbox, *label, *event_box;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
event_box = gtk_event_box_new();
label = gtk_label_new("Add event box");
gtk_container_add(GTK_CONTAINER(window), vbox);
/* The default event mask for GtkEventBox already includes
* GDK_BUTTON_PRESS_MASK but it is not documented.
* Better to be safe than sorry...
*/
gtk_widget_add_events(event_box, GDK_BUTTON_PRESS_MASK);
g_signal_connect(event_box, "button-press-event", G_CALLBACK(main_event_box), vbox);
gtk_container_add(GTK_CONTAINER(event_box), label);
gtk_container_add(GTK_CONTAINER(vbox), event_box);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
我有一个自定义小部件,例如按钮,它具有下一个结构
GtkWidget* button_new(ServerEntity *server)
{
GtkWidget *fixed;
GtkWidget *favoriteEventBox;
GtkWidget *eventBox;
fixed= gtk_fixed_new();
eventBox = gtk_event_box_new();
favoriteEventBox = gtk_event_box_new();
gtk_fixed_put(GTK_FIXED(fixed), eventBox, 0,0);
gtk_fixed_put(GTK_FIXED(fixed), favoriteEventBox, 183,8);
g_signal_connect (G_OBJECT (eventBox),
"button_press_event",
G_CALLBACK (on_event_box_button_press),
server);
g_signal_connect (G_OBJECT (favoriteEventBox),
"button_press_event",
G_CALLBACK (on_favorite_box_button_press),
server);
g_signal_connect (G_OBJECT (fixed),
"draw",
G_CALLBACK (on_fixed_draw),
server);
return fixed;
}
我把它放到vbox里,然后放到scrollable里window:
GtkWidget *scroll_window;
scroll_window = gtk_scrolled_window_new(NULL, NULL);
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll_window), box);
return scroll_window;
box 在 c 文件中仍然可见,稍后我用它来动态添加小部件。主机小部件是单一的,所以我可以做到。
然后我把它放入gtk_fixed、gtk_fixed和window
当我在所有小部件构建过程中添加我的自定义按钮时,它会在两个嵌套框上收到按钮按下和绘制信号。但是当我稍后添加按钮时,只有当我拉动滚动条时才会调用绘制信号。
这就是我在构造和执行期间添加按钮的方式。
void server_list_set_servers(SERVER_ENTITY_CONTAINER* servers)
{
int servers_count = server_entity_container_get_items_count(servers);
int j = 0;
int i = 0;
for (i = 0; i < servers_count; i++)
{
GtkWidget* button;
ServerEntity* server = server_entity_container_get_item_at(servers, i);
button = button_new(server);
// gtk_table_attach_defaults (GTK_TABLE (table), button, j, j + 1, i, i + 1);
gtk_box_pack_end(GTK_BOX(box), button, TRUE, TRUE, 5);
gtk_widget_show (button);
}
}
并且在构建期间按钮仍然接收所有信号,但在它旁边,即时添加 - 没有。
尝试将 "event" 信号连接到所有设备,已删除 scrollable_window,将框更改为 table - 不起作用。为什么会这样?
主循环启动后,GTK 系统无法将委托函数连接到信号。 因此,将整个视图重新创建为 window 是一个很好的做法。
在我的例子中,我从登录 GtkWindow 的用户那里获取凭据,调用 gtk_quit,向服务器发出两次请求 - 首先验证凭据,然后获取数据,然后才创建包含所有数据的 Main GtkWindow手,并根据需要用任意数量的按钮填充它。
我不明白你说的一半,所以也许我没有理解你真正的问题,但我知道你可以动态更改 GUI,连接或不连接信号,没有任何问题。
#include <gtk/gtk.h>
static void
child_button(GtkButton *button)
{
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"A child button has been clicked");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
static void
main_button(GtkButton *button, GtkContainer *vbox)
{
GtkWidget *widget = gtk_button_new_with_label("New button");
g_signal_connect(widget, "clicked", G_CALLBACK(child_button), NULL);
gtk_container_add(vbox, widget);
gtk_widget_show(widget);
}
int main(int argc, char **argv)
{
GtkWidget *window, *vbox, *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_container_add(GTK_CONTAINER(window), vbox);
button = gtk_button_new_with_label("Add button");
g_signal_connect(button, "clicked", G_CALLBACK(main_button), vbox);
gtk_container_add(GTK_CONTAINER(vbox), button);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
您也可以准备小部件(连接或未连接到信号)并稍后添加,只需重新排列上面代码段中的代码即可。信号毕竟只是 C 回调。
附录
我更新了上面的代码以使用 GtkEventBox
和 button-press-event
信号只是为了表明改变小部件或信号不会改变最终结果。
#include <gtk/gtk.h>
static gboolean
child_event_box(GtkEventBox *event_box)
{
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"A button has been pressed inside a child event box");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return FALSE;
}
static gboolean
main_event_box(GtkEventBox *event_box, GdkEvent *event, GtkContainer *vbox)
{
GtkWidget *label = gtk_label_new("Dynamic event box");
GtkWidget *widget = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(widget), label);
g_signal_connect(widget, "button-press-event", G_CALLBACK(child_event_box), NULL);
gtk_container_add(vbox, widget);
gtk_widget_show_all(widget);
return FALSE;
}
int main(int argc, char **argv)
{
GtkWidget *window, *vbox, *label, *event_box;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
event_box = gtk_event_box_new();
label = gtk_label_new("Add event box");
gtk_container_add(GTK_CONTAINER(window), vbox);
/* The default event mask for GtkEventBox already includes
* GDK_BUTTON_PRESS_MASK but it is not documented.
* Better to be safe than sorry...
*/
gtk_widget_add_events(event_box, GDK_BUTTON_PRESS_MASK);
g_signal_connect(event_box, "button-press-event", G_CALLBACK(main_event_box), vbox);
gtk_container_add(GTK_CONTAINER(event_box), label);
gtk_container_add(GTK_CONTAINER(vbox), event_box);
gtk_widget_show_all(window);
gtk_main();
return 0;
}