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;
}
过去一个月我尝试学习将 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;
}