Hello everyone,
I'm currently trying to convert my PyGTK application to C, everything was
working as expected until I hit an issue with retrieving label name of my notebook widget.
Below is a short example of what I'm trying to achieve..
GtkBuilder *builder = NULL;
GtkWidget *window = NULL;
GtkWidget *notebook = NULL;
GError *error = NULL;
void on_page_switch(GtkNotebook *notebook, gpointer data)
{
// gtk_notebook_get_tab_label_text(GtkNotebook *notebook,GtkWidget *child)
}
int main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
builder = gtk_builder_new ();
if( ! gtk_builder_add_from_file( builder, "data/glade.glade", &error ) )
{
g_warning( "%s", error->message );
g_free( error );
return( 1 );
}
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_resizable (GTK_WINDOW(window), FALSE);
g_signal_connect(window, "destroy", GTK_SIGNAL_FUNC (on_window_destroy), NULL);
notebook = GTK_WIDGET (gtk_builder_get_object (builder, "notebook1"));
g_signal_connect(GTK_NOTEBOOK (notebook), "switch-page", GTK_SIGNAL_FUNC(on_page_switch), NULL);
gtk_builder_connect_signals (builder, NULL);
g_object_unref (G_OBJECT (builder));
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
Could you please give me some pointers as how to get the current tab's label name?
I believe it should be this function gtk_notebook_get_tab_label_text(GtkNotebook *notebook, GtkWidget *child) , however I was unable to get it working too.
Apologies for my bad english.
Thanks in advance,
Alex
/// EDIT ////
It was actualy the call-back function it self that was wrong..
I have missed couple of pointers that are passed with the "switch-page" event.
void on_page_switch(GtkNotebook * notebook, GtkWidget *page, guint page_num, gpointer user_data)
{
GtkWidget * child = gtk_notebook_get_nth_page(notebook, page_num);
printf(" -> %i \n", gtk_notebook_page_num(notebook, child));
}
Correct, you should be able to use gtk_notebook_get_tab_label_text() to do this.
You need a pointer to the child widget (page content) whose label you're interested in, you can use gtk_notebook_get_nth_page() to get that if you don't have the notebook children handy.
It's hard to help more since you didn't specify what problems you ran in to when you tried it.
Related
I am trying to make UI using GTK in c for raspberry pi 4. I want to change the visibility of different widgets based on button click just to simulate a new page. I have tried everything available on the internet but as I am not that good at coding I cant figure out what is wrong.
can someone please help ?
This program compiles but when I press the button it gives error " assertion failed on gtk_widget_show " and also on widget hide. Also a segmentation fault occurs and the program crashes.
I am using cmake to compile my code. I have attached the error screen shot.
#include <gtk/gtk.h>
typedef struct AppData
{
GtkWidget *label1;
GtkWidget *label2;
} AppData;
static void button1 (gpointer data)
{
AppData *data2 = (AppData*)data;
gtk_widget_hide(data2->label1);
gtk_widget_show(data2->label2);
}
static void button2 ( gpointer data)
{
AppData *data2 = (AppData*)data;
gtk_widget_show(data2->label1);
gtk_widget_hide(data2->label2);
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *fixed;
GtkWidget *btn1;
GtkWidget *btn2;
GtkWidget *box1;
GtkWidget *box2;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "ethercat test 1");
gtk_window_set_default_size(GTK_WINDOW(window), 1000,500);
fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), fixed);
box1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
gtk_fixed_put(GTK_FIXED(fixed), box1, 0,0);
box2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
gtk_fixed_put(GTK_FIXED(fixed), box2, 100,100);
AppData *app_data = g_new0 (AppData, 2);
app_data->label1 = gtk_label_new("label1");
gtk_box_pack_start(GTK_BOX(box1),app_data->label1, TRUE,TRUE,0);
app_data->label2 = gtk_label_new("label2");
gtk_box_pack_start(GTK_BOX(box2),app_data->label2, TRUE,TRUE,0);
btn1 = gtk_button_new_with_label("ethercat 1");
gtk_fixed_put(GTK_FIXED(fixed), btn1, 10, 450);
gtk_widget_set_size_request(btn1, 80,30);
btn2 = gtk_button_new_with_label("ethercat 2");
gtk_fixed_put(GTK_FIXED(fixed), btn2, 110, 450);
gtk_widget_set_size_request(btn2, 80,30);
gtk_widget_show_all(window);
g_signal_connect(G_OBJECT(btn1), "clicked", G_CALLBACK(button1), app_data);
g_signal_connect(G_OBJECT(btn2), "clicked", G_CALLBACK(button2), app_data);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
printf("program end\n");
return (0);
}
enter image description here
The function signature of your "clicked" callbacks is wrong. It should be of the form as described in the documentation:
void on_clicked(
GtkButton* self,
gpointer user_data
)
So for example, your button2() function becomes
static void button2 (GtkButton *btn2, gpointer data)
{
AppData *data2 = (AppData*)data;
gtk_widget_show(data2->label1);
gtk_widget_hide(data2->label2);
}
#include <gtk/gtk.h>
GtkBuilder *builder;
GtkWidget *window;
GtkImage *image;
GtkButton *but;
char s[1000];
void on_button1_button_press_event(GtkWidget *but, gpointer data)
{
strcpy(s, "/home/linux/testing2.png");
gtk_widget_queue_draw (image);
}
int main(void)
{
gtk_init(NULL, NULL);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "/home/linux/gui.xml", NULL);
window = (GtkWidget *) gtk_builder_get_object(builder, "window1");
image = (GtkImage *) gtk_builder_get_object(builder, "image1");
but = (GtkButton *) gtk_builder_get_object(builder, "button1");
gtk_image_set_from_file(image, strcpy(s, "/home/linux/testing1.png"));
g_signal_connect(but, "clicked", G_CALLBACK(on_button1_button_press_event), NULL);
gtk_widget_show(window);
gtk_main();
return 0;
}
When I click on "button1", "callback" function called, and it updates string s then I want gtk refresh "image1" with gtk_widget_queue_draw. But "image1" have not changed.
gtk_widget_queue_draw() takes a string with the filename of the image. But it does not keep the string you pass. Instead the widget stores the whole loaded image.
So your s variable is useless, and changing it does nothing. You should do instead, in main():
gtk_image_set_from_file(image, "/home/linux/testing1.png");
and in the event callback:
gtk_image_set_from_file(image, "/home/linux/testing2.png");
There is no need to call gtk_widget_queue_draw() because changing the image does that automatically.
I'm trying to create a c application with code::block that use Gtk 3 as a graphics library
This version of gtk is a bit different from gtk 2 and not so much tutorials or exampes are avaiable online. I want to use a type named GdkPixmap that permit to load gifs into your windows, after googled it i have found that the type is deprecated and have been eliminated from gtk new version (3). From official documentation (migrate from gtk2 to gtk3) i have found that is possible to use cairo functions to make the works made by GdkPixmap but i havent found how change and migrate.
This code founded on stackoverflow is an example of loading gif into window using gtk2 that doesnt work on gtk3 compiler said : error unknown type name 'GdkPixmap'
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
GdkPixbuf *load_pixbuf_from_file (const char *filename)
{
GError *error = NULL;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
if (pixbuf == NULL)
{
g_print ("Error loading file: %d : %s\n", error->code, error->message);
g_error_free (error);
exit (1);
}
return pixbuf;
}
GdkPixbufAnimation *load_pixbuf_animation_from_file (const char *filename)
{
GError *error = NULL;
GdkPixbufAnimation *pixbuf = gdk_pixbuf_animation_new_from_file (filename, &error);
if (pixbuf == NULL)
{
g_print ("Error loading file: %d : %s\n", error->code, error->message);
g_error_free (error);
exit (1);
}
return pixbuf;
}
int main (int argc, char **argv)
{
GtkWidget *window = NULL;
GdkPixbuf *image = NULL;
GdkPixbufAnimation * anim = NULL;
GtkWidget *widget = NULL;
GdkPixmap *background = NULL;
GtkStyle *style = NULL;
gtk_init (&argc, &argv);
/* Load a non animated gif */
image = load_pixbuf_from_file ("C://Users//Pcc//Downloads//66.gif");
// widget = gtk_image_new_from_pixbuf (image);
gdk_pixbuf_render_pixmap_and_mask (image, &background, NULL, 0);
style = gtk_style_new ();
style->bg_pixmap [0] = background;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW(window), "Load Image");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
gtk_widget_set_style (GTK_WIDGET(window), GTK_STYLE (style));
gtk_window_set_transient_for (GTK_WINDOW (window), NULL);
GtkWidget *hbox = NULL;
hbox = gtk_hbox_new (0, FALSE);
gtk_container_add (GTK_CONTAINER(window), hbox);
GtkWidget *button = NULL;
button = gtk_button_new_with_label ("Sonic");
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
Use and install a obsolete gtk i dont think is good
Please to post examples of code that works on gtk3 that load gifs
There's a specific GdkPixmap to Cairo migration guide right inside the official GTK 3 documentation.
I am new to GTK and GALDE. I am making a normal GUI in which I have one start button and one update button, so that if I click on start button, start should be displayed in text entry and same for the update button.I am using text entry and its buffer for start and update. Everything is running fine but I am getting warning
passing argument 1 of ‘gtk_entry_get_buffer’ from incompatible pointer type [enabled by default] and
assignment from incompatible pointer type [enabled by default]
Please help in removing these errors.!
Below is the code which I am using
GtkBuilder *builder;
GtkWidget *main_window;
GtkWidget *start_button;
GtkWidget *update_button;
GtkWidget *start_entry;
GtkWidget *update_entry;
GtkWidget *start_entry_buffer;
GtkWidget *update_entry_buffer;
void on_start_button_clicked(GtkButton *start_button)
{
gtk_entry_buffer_set_text (start_entry_buffer,"start ",-1); //error
}
void on_update_button_clicked(GtkButton *update_button)
{
gtk_entry_buffer_set_text (update_entry_buffer,"update ",-1);//error
}
int main(int argc, char *argv[])
{
gtk_init (&argc, &argv);
builder = gtk_builder_new();
if(gtk_builder_add_from_file (builder, "example.glade", NULL) == 0)
{
printf("Error Glade File not Found\n");
exit(0);
}
main_window = GTK_WIDGET (gtk_builder_get_object (builder, "main_window"));
start_button = GTK_WIDGET (gtk_builder_get_object (builder, "start_button"));
update_button = GTK_WIDGET (gtk_builder_get_object (builder, "update_button"));
start_entry = GTK_WIDGET (gtk_builder_get_object (builder, "start_entry"));
start_entry_buffer = gtk_entry_get_buffer (start_entry);//error
update_entry = GTK_WIDGET (gtk_builder_get_object (builder, "update_entry"));
update_entry_buffer = gtk_entry_get_buffer (update_entry);//error
gtk_builder_connect_signals(builder, NULL);
g_object_unref (G_OBJECT (builder));
gtk_widget_show (main_window);
gtk_main ();
return 0;
}
Thanks.!
Did you notice the GTK_WIDGET(...) casts around all your gtk_builder_get_object() calls? It's the same idea for casting a GtkWidget to a GtkEntry: wrap your variable around a GTK_ENTRY(...) and it should work. There's one of these for every GTK+ and GLib type. In addition, using these function casts will give you warnings at runtime if you use the wrong variable in your cast.
I have a main window with a menu wich opens another window. This secondary window has a button Close. That button has the signal clicked connected. My problem is that I don't know how to close/destroy that parent window. I have tried with gtk_widget_destroy, but an error appears because window is not a widget .... I haven't found any function to destroy the parent window ....
Can anyone show me the way, please?
Thanks in advance.
-----------------------------------------------
Ok. I post a piece of code. When I execute the program I click in "Open window" button. A new window is openned with one button "Close". If I click in "Close" button I get next error in terminal: (Windows:13801): Gtk-CRITICAL **: gtk_widget_destroy: assertion `GTK_IS_WIDGET (widget)' failed
The code is:
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
void open_window(GtkWidget *widget, gpointer window);
void close_window(GtkWidget *widget, gpointer window);
int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *fixed;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Windows");
gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), fixed);
button = gtk_button_new_with_label("Open window");
gtk_fixed_put(GTK_FIXED(fixed), button, 50, 50);
gtk_widget_set_size_request(button, 80, 35);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(open_window), G_OBJECT(window));
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
void open_window(GtkWidget *widget, gpointer window)
{
GtkBuilder *builder;
GtkWidget *secondWindow = NULL;
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "secondWindow.glade", NULL);
secondWindow = GTK_WIDGET (gtk_builder_get_object (builder, "secondWindow"));
gtk_builder_connect_signals (builder, NULL);
g_object_unref (G_OBJECT (builder));
gtk_window_set_modal(GTK_WINDOW(secondWindow), TRUE);
gtk_widget_show_all(secondWindow);
}
void close_window(GtkWidget *widget, gpointer window)
{
gtk_widget_destroy(GTK_WIDGET(window));
}
In file "secondWindow.glade" is defined a window, a table and a button placed in the middle cell of the table. Also, it is defined a handle for the "clicked" event button named "close_window".
Link to glade file if anyone wants to execute it: https://sites.google.com/site/marvalsiteimages/secondWindow.glade
I hope this could help you to understand my problem.
Thansk.
-------------------------------------------------
Final code based on the response:
void open_window(GtkWidget *widget, gpointer window)
{
GtkBuilder *builder;
GtkWidget *secondWindow = NULL;
GtkWidget *closeButton = NULL;
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "secondWindow.glade", NULL);
secondWindow = GTK_WIDGET (gtk_builder_get_object (builder, "secondWindow"));
closeButton = GTK_WIDGET (gtk_builder_get_object (builder, "closeWindowButton"));
g_signal_connect (G_OBJECT (closeButton),
"clicked",
G_CALLBACK (close_window),
G_OBJECT (secondWindow)); // here is the magic: the callback will get the window to close
g_object_unref (G_OBJECT (builder));
gtk_window_set_modal(GTK_WINDOW(secondWindow), TRUE);
gtk_widget_show_all(secondWindow);
}
Your problem is that the "clicked" signal of the button of the second window is connected from the glade file. But the signal handler needs a pointer to the window to destroy it. This is passed through the "user_data" parameter of the signal callback.
One way would be by passing the second window as the user_data argument in Glade (give a look at this Glade tutorial), but the argument is supposed to be a pointer, and I don't know how one can do it with glade. EDIT: just click on the user data field associated to this signal in glade, and a popup will allow you to select the object to pass to the signal handler. Just select your "secondWindow" object.
Another way to do it would be to just remove the signal handling from the glade file, and connect manually the clicked signal from code, passing a pointer to the second window as user data:
void open_window(GtkWidget *widget, gpointer window)
{
GtkBuilder *builder;
GtkWidget *secondWindow = NULL;
GtkWidget *closeButton = NULL;
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "secondWindow.glade", NULL);
secondWindow = GTK_WIDGET (gtk_builder_get_object (builder, "secondWindow"));
closeButton = GTK_WIDGET (gtk_builder_get_object (builder, "closeWindowButton"));
g_signal_connect (G_OBJECT (closeButton),
"clicked",
G_CALLBACK (close_window),
G_OBJECT (secondWindow)); // here is the magic: the callback will get the window to close
g_object_unref (G_OBJECT (builder));
gtk_window_set_modal(GTK_WINDOW(secondWindow), TRUE);
gtk_widget_show_all(secondWindow);
}