如何在其他按钮的回调功能没有将信号返回到GTK +中的main()时从按钮发送信号

时间:2014-04-15 06:10:09

标签: c gtk gtk3

这是一个程序,其中有两个按钮(连接断开连接)。点击' connect'按钮,它调用' button1_clicked_do_job()'具有一定条件的功能。另一方面'断开'按钮用于改变while的条件。问题是断开连接按钮不起作用。如何连接'回调函数没有返回到main()?

以下是代码:

#include<gtk/gtk.h>

static int check=1;
void button2_clicked_disconnect(GtkWidget *widget, gpointer data2)
{
    check=0; //Change the condition of while
}

void button1_clicked_do_job(GtkWidget *widget, gpointer data1)
{
    do{
        g_print("Accept Connection\n");
        sleep(2);
    } while(check==1);

    g_print("Reject Connection\n");
}

int main( int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *fixed;
    GtkWidget *button1;
    GtkWidget *button2;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 250, 150);
    gtk_window_set_title(GTK_WINDOW(window), "Connect_N__Disconnect");

    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);

    button1 = gtk_button_new_with_label("Connect");
    gtk_widget_set_size_request(button1, 80, 30);
    gtk_fixed_put(GTK_FIXED(fixed), button1, 30, 50);

    button2 = gtk_button_new_with_label("Disconnect");
    gtk_widget_set_size_request(button2, 80, 30);
    gtk_fixed_put(GTK_FIXED(fixed), button2, 130, 50);

    g_signal_connect(G_OBJECT(button1), "clicked",
                      G_CALLBACK(button1_clicked_do_job),   NULL);

    g_signal_connect(G_OBJECT(button2), "clicked",
                     G_CALLBACK(button2_clicked_disconnect), NULL);

    g_signal_connect_swapped(G_OBJECT(window), "destroy",
                             G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

1 个答案:

答案 0 :(得分:1)

一般来说,你不应该在主线程中运行阻塞代码(比如长时间运行的while循环),因为它会使应用程序无响应 - 所有函数最好都应该以毫秒为单位返回。在你的情况下,你也期望主循环调用你的其他事件处理程序,但永远不会给主循环一个机会:while循环只是永远执行。换句话说:第一个处理程序需要在主循环可以调用第二个处理程序之前返回。

如何解决这个问题取决于你的实际问题:使用异步代码或空闲处理程序应该是第一个选项,而工作线程是另一个选项(但是当你知道实际需要它时,请只添加线程)。也可以手动“泵”事件循环,但这应该是最后一个选项。有关详细信息,请参阅main loop reference

你的例子看起来像这样:

gboolean check_connection (gpointer user_data)
{
    /* g_print what you want based on check value */

    if (check == 0)
        return FALSE;
    return TRUE;
}

void button1_clicked_do_job(GtkWidget *widget, gpointer data1)
{
     g_timeout_add_seconds (2, check_connection, NULL);
}