I have tried past one month learning to use gtk for an application and migrating its code from gtk2 to gtk3. But, one button in a gtk dialog doesn't seem to work well, inspite of whatever i chose the dialog closes without calling the callback function.
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, '\0', 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);
};
The function pmu_server creates a dialog as shown in this image
as per my code when run button is clicked validation_pmu_server is supposed to be called but rather the dialog box simply closes as if the gtk_widget_destroy was called. some of the commented code is the old gtk2 code which i migrated to gtk3.
PS : The above code change from gtk2 to gtk3 is done using this reference
Though I was able to make my code work somewhow, I please request anyone with knowledge to help me understand why this is happening.
Apparantly the problem was due to the below line
g_signal_connect_swapped (pmu_server_window, "response", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
Once I either remove the above line or change it to the below code, everything seems working fine, but I'm still unsure why, i'm guessing that sending "response" as the detailed signal was causing the problem.
g_signal_connect_swapped (pmu_server_window, "destroy", G_CALLBACK (gtk_widget_destroy), pmu_server_window);
The problem you are facing is because of response signal. Whenever any action widget(in your case dialog buttons) is clicked, the response signal is emitted before any other signal(clicked signal). So the function callback associated with signal response will be executed first and then the callback associated with the clicked signal. So, the gtk_widget_destroy is getting called up first and your dialog is closing.
You can either change the callback associated with response or use any other signal.
I have used the below standalone code to reproduce the issue.
#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;
}
Related
I'm trying my hand at writing a C program using GTK (GTK 3 to be precise) (up to now, my experience has mainly been using ObjC, Visual Studio and so on but Cross Platform FTW!)
I need to have a scrollable table, so I've been playing with some of the example code that I've found on the web. The only table code that I've been able to find so far grows the window, and pushes any other elements down the screen as rows are added. I need the table to be a fixed size and to scroll (leaving the header row visible, of course).
This is what I've got so far:
#include <gtk/gtk.h>
enum {
FILE_NAME,
FILE_OFFSET,
FILE_SIZE,
FILE_DESCRIPTION, /* Not used by the view, maybe used elsewhere */
COLOR, /* Just to show how the model can affect the view */
N_COLUMNS
};
void add_row (GtkWidget *widget, gpointer data) {
gtk_list_store_insert_with_values(data, NULL, -1,
COLOR, "blue",
-1);
}
void destroy (GtkWidget *widget,gpointer data) {
gtk_main_quit ();
}
gint main(gint argc, gchar **argv)
{
GtkListStore* model;
GtkWidget* view;
GtkTreeViewColumn* column;
gtk_init(&argc, &argv);
/* MODEL */
model = gtk_list_store_new(N_COLUMNS,
G_TYPE_STRING, /* FILE_NAME */
G_TYPE_UINT, /* FILE_OFFSET */
G_TYPE_UINT, /* FILE_SIZE */
G_TYPE_STRING, /* FILE_DESCRIPTION */
G_TYPE_STRING /* COLOR */
);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "test name",
FILE_OFFSET, 0,
FILE_SIZE, 10,
-1);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "Dummy",
FILE_OFFSET, 123,
COLOR, "black",
-1);
/* VIEW */
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
g_object_unref(model);
column = gtk_tree_view_column_new_with_attributes("Name",
gtk_cell_renderer_text_new(),
"text", FILE_NAME,
"background", COLOR,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Offset",
gtk_cell_renderer_spin_new(),
"text", FILE_OFFSET,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Size",
gtk_cell_renderer_text_new(),
"text", FILE_SIZE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Test App");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
/* Button */
GtkWidget *button;
button = gtk_button_new_with_label ("Add row");
g_signal_connect (button, "clicked", G_CALLBACK(add_row), model);
/* Layoutbox */
GtkWidget *layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), layout_box);
/* Scrollview */
GtkWidget *scrollview = gtk_layout_new(NULL, NULL);
g_object_set(G_OBJECT(scrollview), "app-paintable", TRUE, NULL);
gtk_widget_add_events (scrollview, GDK_ALL_EVENTS_MASK);
gtk_layout_put (GTK_LAYOUT (scrollview), view, 10, 10);
gtk_widget_set_size_request(view, 300, 200);
gtk_container_add (GTK_CONTAINER (layout_box), scrollview); //view
gtk_widget_show_all(window);
GdkWindow *win = gtk_layout_get_bin_window (GTK_LAYOUT(scrollview));
gdk_window_set_events (win, gdk_window_get_events (win) | GDK_STRUCTURE_MASK);
gtk_main ();
return 0;
}
It is a bit of a mess at the moment! My apologies - that's partly inexperience with GTK and mostly multiple iterations in trying to get it to work.
At the moment the table displays very briefly before disappearing (that interesting behaviour only started when I tried to make it into a scroll box).
Note, I only want the table to scroll - not the entire window. In a perfect world, the table would be the width of the window (or layout that contains it) but limited to n pixels high, with a scrollbar if the height exceeds that limit.
I'm a simple guy though, so I also want any solution to be simple - so that I can wrap my brain around it!
Any ideas?
You are using a GtkLayout but the widget to use for scrolling is GtkScrolledWindow.
Here's the adapted code:
#include <gtk/gtk.h>
enum {
FILE_NAME,
FILE_OFFSET,
FILE_SIZE,
FILE_DESCRIPTION, /* Not used by the view, maybe used elsewhere */
COLOR, /* Just to show how the model can affect the view */
N_COLUMNS
};
void add_row (GtkWidget *widget, gpointer data) {
gtk_list_store_insert_with_values(data, NULL, -1,
COLOR, "blue",
-1);
}
void destroy (GtkWidget *widget,gpointer data) {
gtk_main_quit ();
}
gint main(gint argc, gchar **argv)
{
GtkListStore* model;
GtkWidget* view;
GtkTreeViewColumn* column;
gtk_init(&argc, &argv);
/* MODEL */
model = gtk_list_store_new(N_COLUMNS,
G_TYPE_STRING, /* FILE_NAME */
G_TYPE_UINT, /* FILE_OFFSET */
G_TYPE_UINT, /* FILE_SIZE */
G_TYPE_STRING, /* FILE_DESCRIPTION */
G_TYPE_STRING /* COLOR */
);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "test name",
FILE_OFFSET, 0,
FILE_SIZE, 10,
-1);
gtk_list_store_insert_with_values(model, NULL, -1,
FILE_NAME, "Dummy",
FILE_OFFSET, 123,
COLOR, "black",
-1);
/* VIEW */
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
g_object_unref(model);
column = gtk_tree_view_column_new_with_attributes("Name",
gtk_cell_renderer_text_new(),
"text", FILE_NAME,
"background", COLOR,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Offset",
gtk_cell_renderer_spin_new(),
"text", FILE_OFFSET,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
column = gtk_tree_view_column_new_with_attributes("Size",
gtk_cell_renderer_text_new(),
"text", FILE_SIZE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Test App");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
/* Button */
GtkWidget *button;
button = gtk_button_new_with_label ("Add row");
g_signal_connect (button, "clicked", G_CALLBACK(add_row), model);
/* Layoutbox */
GtkWidget *layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), layout_box);
/* Scrollview */
GtkWidget *scrollview = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add (GTK_CONTAINER (scrollview), view);
/* expand to fill all available space left in the window */
gtk_widget_set_hexpand(scrollview, TRUE);
gtk_widget_set_vexpand(scrollview, TRUE);
gtk_container_add (GTK_CONTAINER (layout_box), scrollview); //view
gtk_container_add (GTK_CONTAINER (layout_box), button);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
I have a program using pthreads. I want add an interface using gtk2.0, but have a problem with drawing on window. When I call g_signal_connect(G_OBJECT(window), "configure_event",G_CALLBACK(draw_things), NULL);
lines which I draw appear and at once disappear. If I move a window calling function
gtk_window_move (GTK_WINDOW(widget), 10,10);
or by means of a mouse, lines appear. If I call g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(draw_things), NULL); my lines are displayed correctly, but buttons and labels are not displayed. My code looks like this:
int main(int argc, char *argv[]){
pthread_t tr1;
pthread_t tr2;
pthread_t *trs;
int rc = 0;
type j;
int16_t *id;
type Stop_Point;
GtkWidget *window;
GtkWidget *button;
GtkWidget *table;
GtkWidget *drawing_area;
g_thread_init (NULL);
gdk_threads_init ();
gdk_threads_enter ();
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request(window, width/1.6, height/1.33);
gtk_window_set_position(GTK_WINDOW(window), -1);
gtk_window_set_title (GTK_WINDOW (window), "Window");
g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 2);
table = gtk_table_new ( width/1.6, height/1.33, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
button = gtk_button_new_with_label ("next >>");
gtk_table_attach_defaults (GTK_TABLE (table), button, 1110, 1190, 750, 790);
gtk_widget_show (button);
button = gtk_button_new_with_label ("<< prev");
gtk_table_attach_defaults (GTK_TABLE (table), button, 1020, 1100 , 750, 790);
gtk_widget_show (button);
rc = pthread_create(&tr1, NULL, tr1_func, &id);
rc = pthread_create(&Generator, NULL, tr2_func, &Stop_Point);
trs = (pthread_t*)malloc(Num * sizeof(pthread_t));
for(j = 0; j < Num; j++) {
rc = pthread_create(trs + j, NULL, trs_func, id + j);
}
// g_signal_connect(G_OBJECT(window), "configure-event", GTK_SIGNAL_FUNC(draw_things), NULL);
g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(draw_things), NULL);
gtk_widget_show_all (window);
gtk_main ();
gdk_threads_leave ();
return 0;
}
Fnction for drawing looks like this
gboolean draw_things(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
GdkGC *gc;
gc=gdk_gc_new(GDK_DRAWABLE(widget->window));
gdk_gc_set_line_attributes(gc, 5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 5, 35, 1200, 35);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 1170, 45, 1200, 35);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 1170, 25 , 1200, 35);
// gtk_window_move (GTK_WINDOW(widget), 1,1);
return TRUE;
}
Any help is welcomed, because now I use "configure_event" and call gtk_window_move (GTK_WINDOW(widget), 0,0); every time when I need to draw the picture.
I am trying to create a GUI in GTK using C. I want to have radio buttons but I don't know how to determine which one is selected.
#include <glib.h>
#include <gtk/gtk.h>
static gboolean close_application( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
gtk_main_quit ();
return FALSE;
}
static void btn_selected()
{
//pop-up message; left empty for now
}
int main( int argc,
char *argv[] )
{
GtkWidget *window = NULL;
GtkWidget *box1;
GtkWidget *box2;
GtkWidget *button;
GtkWidget *separator;
GSList *group;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "delete-event",
G_CALLBACK (close_application),
NULL);
gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
box1 = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box1);
gtk_widget_show (box1);
box2 = gtk_vbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
gtk_widget_show (box2);
button = gtk_radio_button_new_with_label (NULL, "button1");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_show (button);
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
button = gtk_radio_button_new_with_label (group, "button2");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button),
"button3");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_show (button);
separator = gtk_hseparator_new ();
gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
gtk_widget_show (separator);
box2 = gtk_vbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
gtk_widget_show (box2);
button = gtk_button_new_with_label ("close");
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (close_application),
window);
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_widget_set_can_default (button, TRUE);
gtk_widget_grab_default (button);
gtk_widget_show (button);
//This button will call the btn_selected method when clicked
button = gtk_button_new_with_label("selected");
g_signal_connect(button,"clicked",G_CALLBACK (btn_selected),NULL);
gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
gtk_widget_show(button);
gtk_widget_show (window);
gtk_main ();
return 0;
}
The GUI comes up without any errors, I just don't know to check which radio button was selected so I can perform an action. Since all the buttons are named button I don't know how to check for a specific one.I got this code from a gtk tutorial online.
Any ideas would be greatly appreciated.
GtkRadioButton is descended from GtkToggleButton so you can connect to the 'toggled' signal or use the 'active' property to the the state of the button.
I've done a little program in C with GTK with a window, a box and a table inside the box. The table is painted with some files. I'd like to refresh the table with other data but I don't know how.
This code launches a window with a GtkTable. This table is filled in the timer handle function. First time draw three lines in order 1,2,3 and last time write three lines in order 3,2,1. But the table never refreshes.
#include <stdlib.h>
#include <gtk/gtk.h>
static gboolean time_handler(GtkWidget *table);
gboolean launched;
int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vboxgeneral;
gchar *title;
GtkWidget *table;
gtk_init(&argc, &argv);
/* WINDOW */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
title = "Test GtkTable";
gtk_window_set_title(GTK_WINDOW(window), title);
gtk_window_set_default_size(GTK_WINDOW(window), 200, 100);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
/* ADDING GTKHBOX TO MAIN WINDOW */
vboxgeneral = gtk_vbox_new(FALSE, 0);
/* ADDING GTKTABLE TO VBOX */
table = gtk_table_new(1,1,FALSE);
gtk_box_pack_start(GTK_BOX(vboxgeneral), table, FALSE, FALSE, 0);
/* SHOW ALL */
gtk_widget_show_all(window);
/* ACTIONS */
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
/* START TIMER */
g_timeout_add(10000, (GSourceFunc) time_handler, (gpointer) window);
time_handler(table);
gtk_main();
return 0;
}
static gboolean time_handler(GtkWidget *table)
{
GtkWidget *widget;
gboolean result = FALSE;
/* ADDING TABLE DEFINITION */
if(!launched)
{
table = gtk_table_new(3,1,FALSE);
widget = gtk_label_new("File 1");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 0, 1);
widget = gtk_label_new("File 2");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 1, 2);
widget = gtk_label_new("File 3");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 2, 3);
launched = TRUE;
result = TRUE;
g_print("Timer executed fisrt time!\n");
}
else
{
table = gtk_table_new(3,1,FALSE);
widget = gtk_label_new("File 3");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 0, 1);
widget = gtk_label_new("File 2");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 1, 2);
widget = gtk_label_new("File 1");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 2, 3);
result = FALSE;
g_print("Timer executed last time!\n");
}
gtk_widget_draw(table, NULL);
return result;
}
Your code has several issues:
You didn't add your vbox to your window. That can be done with the following code:
gtk_container_add (GTK_CONTAINER (window), vboxgeneral);
You were passing the wrong parameter (the table widget) to your time_handler function. In that function, you created a new table losing the previous one which you packed into a vbox. What you can do is destroy the previous table and create a new one with the new labels and pack it into the vbox.
The call time_handler(table) made in your main function is completely unnecesary. The timer already does that for you.
The revised code I made (a working code which does what you asked) as follows:
#include <stdlib.h>
#include <gtk/gtk.h>
static gboolean time_handler(GtkWidget *table);
gboolean launched;
int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vboxgeneral;
gchar *title;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
title = "Test GtkTable";
gtk_window_set_title(GTK_WINDOW(window), title);
gtk_window_set_default_size(GTK_WINDOW(window), 200, 100);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
/* ADDING GTKHBOX TO MAIN WINDOW */
vboxgeneral = gtk_vbox_new(FALSE, 0);
/* This step was missing! */
gtk_container_add (GTK_CONTAINER (window), vboxgeneral);
gtk_widget_show_all(window);
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
/* START TIMER */
/* refresh in 1 second, change to the desired amount */
g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) vboxgeneral);
gtk_main();
return 0;
}
static gboolean time_handler(GtkWidget *vbox)
{
GtkWidget *widget;
static GtkWidget *table = NULL;
gboolean result = FALSE;
/* if you want only the new labels to appear and not the previous ones you can: */
/* 1. destroy the table and create a new one. This will be done */
/* 2. hide all previous labels in the table and create and show the new ones */
if (table != NULL) {
/* destroy previous table packed into vbox */
gtk_widget_destroy(table);
}
table = gtk_table_new(3,1,FALSE); /* create new table for the new labels */
if(!launched) {
widget = gtk_label_new("File 1");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 0, 1);
widget = gtk_label_new("File 2");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 1, 2);
widget = gtk_label_new("File 3");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 2, 3);
launched = TRUE;
result = TRUE;
g_print("Timer executed first time!\n");
} else {
/* table = gtk_table_new(3,1,FALSE); */
widget = gtk_label_new("File 3");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 0, 1);
widget = gtk_label_new("File 2");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 1, 2);
widget = gtk_label_new("File 1");
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
gtk_table_attach_defaults (GTK_TABLE (table), widget, 0, 1, 2, 3);
launched = FALSE;
result = FALSE;
g_print("Timer executed last time!\n");
}
/* ADD THE NEWLY CREATED TABLE TO THE VBOX */
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
/* VERY IMPORTANT: SHOW ALL THE NEW LABELS PACKED INTO THE TABLE */
gtk_widget_show_all(table);
return result;
}
I need to output the i progress bars and update them all. But only the last one updates i times. This is the code:
static void calculaPi (GtkButton * boton, Datos * dDatos){
const char * threads;
GtkWidget * barra, *bot2, *button, *progress, *vbox;
threads = gtk_entry_get_text(GTK_ENTRY(dDatos->dthreads ));
gint ithreads = 1;
ithreads = atoi(threads);
barra = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title((GtkWindow *) barra, "Loteria de Threads");
gtk_window_set_default_size(GTK_WINDOW(barra), 300, ithreads*30);
gtk_window_set_position(GTK_WINDOW(barra), GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label ("Click me!");
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (barra), vbox);
for (gint i = 1 ; i <= ithreads; i++) {
progress = gtk_progress_bar_new ();
gtk_box_pack_start (GTK_BOX (vbox), progress, FALSE, FALSE, 5);
g_object_set_data (G_OBJECT (barra), "pbar", (gpointer) progress);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (button_clicked), (gpointer) barra);
}
bot2 = gtk_button_new_with_label("Salir");
gtk_box_pack_start (GTK_BOX (vbox), bot2, FALSE, FALSE, 5);
gtk_widget_set_size_request(bot2, 100, 35);
g_signal_connect (G_OBJECT (bot2), "clicked",
G_CALLBACK (destroy),
G_OBJECT (barra));
gtk_widget_show_all(barra);
gtk_main();
}
static void
button_clicked (GtkButton *button,
GtkWidget *barra)
{
GtkProgressBar *progress;
gdouble percent = 0.0;
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
progress = GTK_PROGRESS_BAR (g_object_get_data (G_OBJECT (barra), "pbar"));
while (percent <= 100.0)
{
gchar *message = g_strdup_printf ("%.0f%% Complete", percent);
gtk_progress_bar_set_fraction (progress, percent / 100.0);
gtk_progress_bar_set_text (progress, message);
while (gtk_events_pending ())
gtk_main_iteration ();
g_usleep (500000);
percent += 5.0;
}
}
With this line:
g_object_set_data (G_OBJECT (barra), "pbar", (gpointer) progress);
you override previous value of "pbar" data entry on each loop iteration. When you later retrive it in button_clicked() you get the last set value, i.e. the last progress bar.
In this particular case you can just pass progress widget as user data (and drop g_object_[gs]et_data() calls) for button_clicked() callback: the function doesn't use current barra window for anything else anyway.
In a more general way, you should learn how to use your own structures for user data parameters. A common way is to declare and use one structure for given toplevel type and store pointers to widgets you need to access from callbacks in it.