信号在插入飞行小部件时不起作用

时间:2015-04-14 00:37:05

标签: c gtk gtk3

我有一个自定义小部件,比如按钮,它有下一个结构

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中,然后放在可滚动的窗口中:

    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;

框在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);
    }
}

施工期间按钮仍然可以接收所有信号,但在它旁边,添加了飞行 - 没有。

尝试连接&#34;事件&#34;信号发送到所有内容,删除了scrollable_window,将框更改为表格 - 不起作用。为什么会这样?

2 个答案:

答案 0 :(得分:1)

我不明白你说的一半,所以也许我没有得到你真正的问题,但我知道你可以动态地改变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回调。

附录

我更新了上面的代码,使用GtkEventBoxbutton-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;
}

答案 1 :(得分:-1)

GTK系统在主循环启动后无法将委托功能连接到信号。 因此,将整个视图重新创建为窗口是一种很好的做法。

在我的情况下,我在登录GtkWindow中从用户获取凭据,调用gtk_quit,向服务器发出两个请求 - 首先验证creds,第二次抓取数据,然后我创建Main GtkWindow并掌握所有数据,并填充它我想要的任意数量的按钮。