g_signal_connect_swapped 连接失败

g_signal_connect_swapped fails to connect

过去一个月我尝试学习将 gtk 用于应用程序并将其代码从 gtk2 迁移到 gtk3。但是,gtk 对话框中的一个按钮似乎无法正常工作,无论我选择什么,对话框都会在不调用回调函数的情况下关闭。

int validation_pmu_server (GtkButton *button, gpointer udata)
{

/* local variables */
int tmp_p;
char *msg;
const char *text1, *text2;

/* Get the text entries filled by user */
text1 = gtk_entry_get_text(GTK_ENTRY(p_port));
text2 = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(p_protocol));

if(!isNumber((char *)text1) && (atoi(text1) < 1500 || (atoi(text1) > 65535)))   /* Check for valid port number */       
{ 
    msg = "\tPlease enter valid value for PMU Server Port\t\n";
    validation_result (msg);        /* Show the unsuccess message to user */
    return 0;
}
else
{
    strncpy(PMUprotocol, text2, 3);
    PMUport = atoi(text1);

    if(!strcmp(text2, "UDP"))
        tmp_p = 1;          
    else
        tmp_p = 2;          

    p1 = *ShmPTR;
    p1.cfg_bit_change_info = 0;
    ShmPTR->cfg_bit_change_info = 0;
    ShmPTR->serverProtocol = tmp_p;
    ShmPTR->serverPort = atoi(text1);

    p1.pid = ShmPTR->pid;

    kill(p1.pid, SIGUSR2);
    printf("PORT & Protocol information has sent to PMU Server through signal.\n");

    memset(pmuFilePath, '[=11=]', 200);

    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->start_server), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->open_cfg), FALSE);

    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->create_cfg_button), TRUE);                    
    gtk_widget_set_sensitive(GTK_WIDGET(pmu_data->menu_setup_cfg), TRUE);                   

    /* Close/destroy the pmu_server_window */
    gtk_widget_destroy(pmu_server_window);

    return 1;
}
};

void pmu_server ()
{
/* local variables */
GtkWidget *table, *label, *cancel_button;
GtkWidget *valdbutton, *help_button;

/* Create a new dialog window for PMU Server Setup */
pmu_server_window = gtk_dialog_new ();
g_signal_connect (pmu_server_window, "destroy", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
gtk_window_set_title (GTK_WINDOW (pmu_server_window), "PMU Server Setup");
gtk_container_set_border_width (GTK_CONTAINER (pmu_server_window), 10);

/* Create a table of 4 by 2 squares. */
table = gtk_grid_new (); // table = gtk_table_new (6, 2, FALSE);

/* Set the spacing to 50 on x and 5 on y */
gtk_grid_set_row_spacing (GTK_GRID(table), 16); // gtk_table_set_row_spacings (GTK_TABLE  (table), 8);
gtk_grid_set_column_spacing (GTK_GRID(table), 16); // gtk_table_set_col_spacings (GTK_TABLE  (table), 2);

/* Pack the table into the window */
//gtk_box_pack_start (GTK_BOX (GTK_DIALOG(pmu_server_window)->vbox), table, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG(pmu_server_window))), table, TRUE, TRUE, 0);
gtk_widget_show (table);

/* Add few buttons to the bottom of the dialog */
valdbutton = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Run", GTK_RESPONSE_OK); // gtk_button_new_with_label ("Run");
help_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Help", GTK_RESPONSE_APPLY); // gtk_button_new_with_label ("Help");
cancel_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Cancel", GTK_RESPONSE_CLOSE); //gtk_button_new_with_label ("Cancel");

/* This simply creates a grid of toggle buttons on the table */
label = gtk_label_new (" ");
markup = g_markup_printf_escaped ("<span foreground=\"#990033\" font='12'><b>Enter PMU Server Details</b></span>");
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_grid_attach (GTK_GRID (table), label, 0,0,2,1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 0, 1);
gtk_widget_show (label);
g_free (markup);

label = gtk_label_new ("Server Port");
    // gtk_misc_set_alignment (GTK_MISC(label),0,0);
    gtk_label_set_xalign (GTK_LABEL (label),0);
    gtk_label_set_yalign (GTK_LABEL (label),0);
gtk_grid_attach (GTK_GRID (table), label, 0, 2, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
gtk_widget_show (label);

label = gtk_label_new ("Protocol");
    // gtk_misc_set_alignment (GTK_MISC(label),0,0);
    gtk_label_set_xalign (GTK_LABEL (label),0);
    gtk_label_set_yalign (GTK_LABEL (label),0);
gtk_grid_attach (GTK_GRID (table), label, 0, 3, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
gtk_widget_show (label);

/* Create text boxes for user to enter appropriate values */
p_port = gtk_entry_new();
gtk_entry_set_max_length ((GtkEntry *)p_port, 5);
gtk_grid_attach (GTK_GRID (table), p_port, 1, 2, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), p_port, 1, 2, 2, 3);
gtk_widget_show (p_port);

label = gtk_label_new (" ");
markup = g_markup_printf_escaped ("<span foreground=\"#333333\" font='8'><b>Note : Use the unreserved ports for PMU Server.</b></span>");
gtk_label_set_markup (GTK_LABEL (label), markup);
    // gtk_misc_set_alignment (GTK_MISC(label),0,0);
    gtk_label_set_xalign (GTK_LABEL (label),0);
    gtk_label_set_yalign (GTK_LABEL (label),0);
gtk_grid_attach (GTK_GRID (table), label, 0, 5, 2, 1); // gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 5, 6);
gtk_widget_show (label);
g_free (markup);

/* Create combo boxe for user with some fixed values */
p_protocol = gtk_combo_box_text_new();
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p_protocol), "UDP");
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p_protocol), "TCP");
gtk_combo_box_set_active(GTK_COMBO_BOX(p_protocol), 0);
gtk_grid_attach (GTK_GRID (table), p_protocol, 1, 3, 1, 1); // gtk_table_attach_defaults (GTK_TABLE (table), p_protocol, 1, 2, 3, 4);
gtk_widget_show (p_protocol);

/* Signal handling for buttons on PMU Server Setup Window */
g_signal_connect_swapped (valdbutton, "clicked", G_CALLBACK (validation_pmu_server), valdbutton);
g_signal_connect_swapped (help_button, "clicked", G_CALLBACK (Pmu_Help), NULL);
g_signal_connect_swapped (cancel_button, "clicked", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (gtk_widget_destroy), pmu_server_window);

/* This makes it so the button is the default. */
// gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pmu_server_window)->action_area), valdbutton, TRUE, TRUE, 0);
// gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pmu_server_window)->action_area), help_button, TRUE, TRUE, 0);
// gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pmu_server_window)->action_area), cancel_button, TRUE, TRUE, 0);        

/* This grabs this button to be the default button. Simply hitting the "Enter" key will cause this button to activate. */
gtk_widget_grab_default (valdbutton);
gtk_widget_show (valdbutton);
gtk_widget_grab_default (help_button);
gtk_widget_show (help_button);
gtk_widget_grab_default (cancel_button);
gtk_widget_show (cancel_button);

/* Finally show the pmu_server_window */
gtk_widget_show (pmu_server_window);
};

函数 pmu_server 创建一个如图所示的对话框 in this image

根据我的代码,当单击 运行 按钮时 validation_pmu_server 应该被调用,但对话框只是关闭,就好像 gtk_widget_destroy 被调用一样。一些注释代码是我迁移到 gtk3 的旧 gtk2 代码。

PS :上述代码从 gtk2 到 gtk3 的更改是使用 完成的 尽管我能够使我的代码以某种方式工作,但我请任何有知识的人帮助我理解为什么会这样。

显然问题出在下面这行

g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (gtk_widget_destroy), pmu_server_window);

一旦我删除上面的行或将其更改为下面的代码,一切似乎都工作正常,但我仍然不确定为什么,我猜测发送“响应”作为详细信号导致了问题.

g_signal_connect_swapped (pmu_server_window, "destroy", G_CALLBACK (gtk_widget_destroy), pmu_server_window);

您遇到的问题是因为 response 信号。每当单击任何操作小部件(在您的情况下为对话框按钮)时,都会在任何其他信号(单击信号)之前发出响应信号。因此,与信号 response 关联的函数回调将首先执行,然后与信号 clicked 关联的回调。因此,gtk_widget_destroy 首先被调用,您的对话框正在关闭。

您可以更改与 response 关联的回调或使用任何其他信号。

我使用下面的独立代码重现了这个问题。

#include<stdio.h>
#include <gtk/gtk.h>


void Pmu_Help(){
    printf("Pmu_Help");
    fflush(stdout);
}
void validation_pmu_server(){
    printf("validation_pmu_server");
    fflush(stdout);
}
void response(){
    printf("response");
    fflush(stdout);
}


int main(int argc, char *argv[]) {

    GtkWidget *window;
    GtkWidget * pmu_server_window;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_show(window);
  
    g_signal_connect(window, "destroy",
      G_CALLBACK(gtk_main_quit), NULL);

    pmu_server_window = gtk_dialog_new ();
    g_signal_connect (pmu_server_window, "destroy", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
    gtk_window_set_title (GTK_WINDOW (pmu_server_window), "PMU Server Setup");
    gtk_container_set_border_width (GTK_CONTAINER (pmu_server_window), 10);

    GtkWidget *table, *label, *cancel_button;
    GtkWidget *valdbutton, *help_button;

    valdbutton = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Run", GTK_RESPONSE_OK); // gtk_button_new_with_label ("Run");
    help_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Help", GTK_RESPONSE_APPLY); // gtk_button_new_with_label ("Help");
    cancel_button = gtk_dialog_add_button((GtkDialog *)pmu_server_window, "Cancel", GTK_RESPONSE_CLOSE); //gtk_button_new_with_label ("Cancel");

    g_signal_connect_swapped (valdbutton, "clicked", G_CALLBACK (validation_pmu_server), valdbutton);
    g_signal_connect_swapped (help_button, "clicked", G_CALLBACK (Pmu_Help), NULL);
    g_signal_connect_swapped (cancel_button, "clicked", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
    g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (response), pmu_server_window);
    //g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
    gtk_widget_show(pmu_server_window);

    gtk_main();

  return 0;
}