utter total 100% coding noob here. I am experimenting in GTK+ and C and I'm trying to create a basic window which has an image over it.
This is my (probably cringeworthy) code:
#include <gtk/gtk.h>
int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *fixed;
GtkWidget *button;
GtkImage *image;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "GtkButton");
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), fixed);
image = gtk_image_new();
gtk_image_set_from_file(GTK_IMAGE(image),"/home/testbed/Downloads/efnbxw.jpg");
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(gtk_main_quit), 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;
}
What did I do wrong?
Scrap the above code, it's just entirely incorrect
#include <gtk/gtk.h>
int main( int argc, char *argv[])
{
GtkWidget *window, *image;
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), 230, 150);
gtk_window_set_title(GTK_WINDOW(window), "Image");
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_container_set_border_width(GTK_CONTAINER(window), 2);
image = gtk_image_new_from_file("/home/testbed/Downloads/efnbxw.jpg");
gtk_container_add(GTK_CONTAINER(window), image);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
^^Heres my new code. It compiles and displayed a window with my selected image.
Can anyone here help me code this so that when the image is clicked, the application closes?
Image widgets are one of those that don't capture events (because they don't have their own window). You can place such widgets in an eventbox widget and enable the capture of events such as button presses. Try this modified version of your update.
#include <gtk/gtk.h>
int main( int argc, char *argv[])
{
GtkWidget *window, *image;
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), 230, 150);
gtk_window_set_title(GTK_WINDOW(window), "Image");
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_container_set_border_width(GTK_CONTAINER(window), 2);
image = gtk_image_new_from_file("/home/testbed/Downloads/efnbxw.jpg");
//gtk_container_add(GTK_CONTAINER(window), image);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget* eventBox = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(window), eventBox);
// Capture button presses.
gtk_widget_add_events (eventBox, GDK_BUTTON_PRESS_MASK);
g_signal_connect(G_OBJECT(eventBox), "button-press-event", G_CALLBACK(gtk_main_quit), NULL);
gtk_container_add(GTK_CONTAINER(eventBox), image);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Segmenation fault means that you are accesing memory positions that are out of the bounds defined in your program.From the above code i assume that one of your pointers causes the problem..
Related
I'm developing a program using GTK3, glade and C language, but in one of the windows i need to make only part of it scrollable (the size of the total scrollable area won't change), but i'm having a hard time with it.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <math.h>
#include <ctype.h>
//login window
GtkBuilder *builder;
GtkWidget *window;
GtkWidget *fixed1;
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *label1;
GtkWidget *entry1;
GtkWidget *entry2;
GtkWidget *icon_entry;
GtkWidget *image;
//register window
GtkWidget *r_window, *r_fixed;
GtkWidget *r_button1, *r_button2, *r_label;
GtkWidget *r_entry1, *r_entry2, *r_entry3;
GtkWidget *r_image;
//menu window
GtkWidget *menu_win, *menu_fixed;
GtkWidget *menu_button1, *menu_button2, *menu_button3;
GtkWidget *menu_button4, *menu_button5, *menu_button6;
//album window
GtkWidget *album_win, *album_fixed;
GtkWidget *album_grid, *album_label1, *album_label2;
GtkWidget *album_view, *album_scroll;
//showing functions
void register_s (){
gtk_widget_show(r_window);
}
void login_s (){
gtk_widget_show(window);
}
void menu_s (){
gtk_widget_show(menu_win);
}
void album_s (){
gtk_widget_show(album_win);
}
//hiding functions
void register_h (){
gtk_widget_hide(r_window);
}
void login_h (){
gtk_widget_hide(window);
}
void menu_h (){
gtk_widget_hide(menu_win);
}
void album_h (){
gtk_widget_hide(album_win);
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
builder = gtk_builder_new_from_file ("testing.glade");
//login window
window = GTK_WIDGET(gtk_builder_get_object(builder, "login_window"));
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
fixed1 = GTK_WIDGET(gtk_builder_get_object(builder, "fixed1"));
label1 = GTK_WIDGET(gtk_builder_get_object(builder, "label1"));
entry1 = GTK_WIDGET(gtk_builder_get_object(builder, "entry1"));
entry2 = GTK_WIDGET(gtk_builder_get_object(builder, "entry2"));
image = GTK_WIDGET(gtk_builder_get_object(builder, "image"));
button1 = GTK_WIDGET(gtk_builder_get_object(builder, "button1"));
g_signal_connect(button1, "clicked", G_CALLBACK(register_s), NULL);
g_signal_connect(button1, "clicked", G_CALLBACK(login_h), NULL);
button2 = GTK_WIDGET(gtk_builder_get_object(builder, "button2"));
g_signal_connect(button2, "clicked", G_CALLBACK(menu_s), NULL);
g_signal_connect(button2, "clicked", G_CALLBACK(login_h), NULL);
gtk_builder_connect_signals(builder, NULL);
//register window
r_window = GTK_WIDGET(gtk_builder_get_object(builder, "r_window"));
g_signal_connect(r_window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
r_button1 = GTK_WIDGET(gtk_builder_get_object(builder, "r_button1"));
r_button2 = GTK_WIDGET(gtk_builder_get_object(builder, "r_button2"));
g_signal_connect(r_button2, "clicked", G_CALLBACK(login_s), NULL);
g_signal_connect(r_button2, "clicked", G_CALLBACK(register_h), NULL);
r_entry1 = GTK_WIDGET(gtk_builder_get_object(builder, "r_entry1"));
r_entry2 = GTK_WIDGET(gtk_builder_get_object(builder, "r_entry2"));
r_entry3 = GTK_WIDGET(gtk_builder_get_object(builder, "r_entry3"));
r_fixed = GTK_WIDGET(gtk_builder_get_object(builder, "r_fixed"));
r_label = GTK_WIDGET(gtk_builder_get_object(builder, "r_label"));
r_image = GTK_WIDGET(gtk_builder_get_object(builder, "r_image"));
//menu window
menu_win = GTK_WIDGET(gtk_builder_get_object(builder, "menu_win"));
g_signal_connect(menu_win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
menu_fixed = GTK_WIDGET(gtk_builder_get_object(builder, "menu_fixed"));
menu_button1 = GTK_WIDGET(gtk_builder_get_object(builder, "menu_button1"));
g_signal_connect(menu_button1, "clicked", G_CALLBACK(album_s), NULL);
g_signal_connect(menu_button1, "clicked", G_CALLBACK(menu_h), NULL);
menu_button2 = GTK_WIDGET(gtk_builder_get_object(builder, "menu_button2"));
menu_button3 = GTK_WIDGET(gtk_builder_get_object(builder, "menu_button3"));
menu_button4 = GTK_WIDGET(gtk_builder_get_object(builder, "menu_button4"));
menu_button5 = GTK_WIDGET(gtk_builder_get_object(builder, "menu_button5"));
menu_button6 = GTK_WIDGET(gtk_builder_get_object(builder, "menu_button6"));
g_signal_connect(menu_button6, "clicked", G_CALLBACK(gtk_main_quit), NULL);
//album window
album_win = GTK_WIDGET(gtk_builder_get_object(builder, "album_win"));
g_signal_connect(album_win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
album_fixed = GTK_WIDGET(gtk_builder_get_object(builder, "album_fixed"));
album_grid = GTK_WIDGET(gtk_builder_get_object(builder, "album_grid"));
album_view = GTK_WIDGET(gtk_builder_get_object(builder, "album_view"));
album_scroll = GTK_WIDGET(gtk_builder_get_object(builder, "album_scroll"));
gtk_range_set_range (GTK_RANGE(album_scroll), 0, 600 );
//g_signal_connect(album_scroll, "change-value", G_CALLBACK(), NULL);
album_label1 = GTK_WIDGET(gtk_builder_get_object(builder, "album_label1"));
album_label2 = GTK_WIDGET(gtk_builder_get_object(builder, "album_label2"));
//main functions
gtk_widget_show(window);
gtk_main();
return EXIT_SUCCESS;
}//main
This is the code i've written so far, i want to keep it as simple as possible cause i'm working with people who don't know GTK.
The current widgets added in glade
The current design of the window
The thing is that i want to put images there, make one side (left of scrollbar) scrollable and displaying the photos and the other side immobile.
I'm new to programming, so i'd appreciate if you could explain it in a simple way.
I am programming on linux program and I am trying to prepare program with GTK+3, but I don't know how close program automatically after execute the function without kill that execute.
the step that i want in my program is:
open gtk window and this window there is button (open Xreader).
press button, it tells system to execute xreader program.
close gtk window automatically without needing to close xreader .
here is my code
#include<stdio.h>
#include<gtk/gtk.h>
static void
open_app(GtkWidget *Widget, gpointer data){
system("xreader");
gtk_main_quit();
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button1;
gtk_init(&argc, &argv);
/*make window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*give name to the window*/
gtk_window_set_title(GTK_WINDOW(window), "launcher");
/*make size of window*/
gtk_window_set_default_size(GTK_WINDOW(window), 700, 700);
/*open the window in the meddal*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
button1 = gtk_button_new_with_label("Open Xreader");
gtk_container_add(GTK_CONTAINER(window), button1);
gtk_widget_show_all(window);
g_signal_connect(button1,"clicked",G_CALLBACK(open_app), NULL);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
everytime trying to execute my program and press the button (open Xreader) gtk not close till close xreader .
You cannot use system here, because according to its documentation, https://man7.org/linux/man-pages/man3/system.3.html
system() returns after the command has been completed.
Since you are using gtk, don't forget library functions provided by glib. It has a bunch of functions related to process and thread handling. For example, you can use GSubprocess class from glib, g_subprocess_new.
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
static void open_app(GtkWidget *Widget, gpointer data) {
g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "xreader", NULL);
gtk_main_quit();
}
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *button1;
gtk_init(&argc, &argv);
/*make window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*give name to the window*/
gtk_window_set_title(GTK_WINDOW(window), "launcher");
/*make size of window*/
gtk_window_set_default_size(GTK_WINDOW(window), 700, 700);
/*open the window in the meddal*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
button1 = gtk_button_new_with_label("Open Xreader");
gtk_container_add(GTK_CONTAINER(window), button1);
gtk_widget_show_all(window);
g_signal_connect(button1, "clicked", G_CALLBACK(open_app), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
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);
}
I have a C GTK3 program that has a notebook with two images. I want to be able to grab the corner of the window and adjust the size of the image currently displayed. What I currently have is a program that once started, the window keeps growing until I kill it from the terminal using ctrl-c. I put a sleep call in the callback to slow it down, but it still grows. How do I stop the window from growing unless I "grab" a corner of the window and adjust it myself?
#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
GtkWidget *notebook;
gboolean resize_image(GtkWidget *widget, GdkRectangle *allocation,
gpointer user_data)
{
int w,h, pagenum;
GdkPixbuf *pxbscaled;
GtkWidget *image;
GdkPixbuf *pixbuf;
pagenum = gtk_notebook_get_current_page (GTK_NOTEBOOK(notebook));
image = gtk_notebook_get_nth_page (GTK_NOTEBOOK(notebook), pagenum);
// GtkImageType image_type = gtk_image_get_storage_type
// (GTK_IMAGE(image));
pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image));
h = allocation->height;
w = (gdk_pixbuf_get_width(pixbuf) * h) / gdk_pixbuf_get_height(pixbuf);
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, w, h, GDK_INTERP_BILINEAR);
printf("Allocation height %d width %d.\n", h, w);
gtk_image_set_from_pixbuf(GTK_IMAGE(image), pxbscaled);
g_object_unref (pxbscaled);
sleep(2);
return FALSE;
}
static gboolean delete( GtkWidget *widget,
GtkWidget *event,
gpointer data )
{
gtk_main_quit ();
return FALSE;
}
int main( int argc,
char *argv[] )
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *table;
GtkWidget *label;
GtkWidget *image;
int i;
char bufferl[32];
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
// gtk_widget_set_size_request (GTK_WIDGET(window), 800, 480);
g_signal_connect (window, "delete-event",
G_CALLBACK (delete), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
table = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), table);
/* Create notebook, place position of tabs */
notebook = gtk_notebook_new ();
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
gtk_grid_attach (GTK_GRID (table), notebook, 0, 6, 3, 3);
gtk_widget_show (notebook);
/* Append pages to the notebook */
for (i = 0; i < 2; i++) {
sprintf(bufferl, "Page %d", i + 1);
if (i == 0) {
image = gtk_image_new_from_file("image1.jpg");
} else {
image = gtk_image_new_from_file("image2.jpg");
}
gtk_widget_set_halign(image, GTK_ALIGN_START);
gtk_widget_set_valign(image, GTK_ALIGN_START);
g_signal_connect(window, "size-allocate",
G_CALLBACK(resize_image), NULL);
label = gtk_label_new (bufferl);
gtk_notebook_append_page (GTK_NOTEBOOK(notebook),
image, label);
}
/* Create a close button */
button = gtk_button_new_with_label ("close");
g_signal_connect (button, "clicked",
G_CALLBACK (delete), NULL);
gtk_grid_attach (GTK_GRID (table), button, 0, 10, 1, 1);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
A user will need to provide image1.jpg and image2.jpg. Edit out the sleep call will result in the program filling the screen extremely quickly.
EDIT: I have also asked this question on the gtk mailing list.
The window with the image was growing because I was applying the size of the window to the image. Hence the image got larger and thus made the window get larger. Which continued in an endless progression, the "size-allocate" signal was constantly being called.
I fixed it by limiting the allocation height in the call back, by multiplying it by 0.75.
Now I can expand and contract the window with ease and it does not grow out of control.
The image does get ugly quite quickly, but that is another problem.
In the following example, compiled with GTK3, GtkExpander collapses unintendedly when I click in the entry field.
#include <gtk/gtk.h>
static void destroy (GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
}
int main( int argc,
char *argv[] )
{
gtk_init (&argc, &argv);
GtkWidget *entry;
entry = gtk_entry_new ();
GtkWidget *expander;
expander = gtk_expander_new ("test");
gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
gtk_container_add (GTK_CONTAINER(expander), entry);
GtkWidget *window;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_add (GTK_CONTAINER(window), expander);
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
However, GtkExpander does not collapse if it is expanded after gtk_widget_show_all(), i.e.:
gtk_widget_show_all (window);
gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
What's wrong with expanding the widget before gtk_widget_show_all()?
This was a bug in GTK+ which is fixed now.
For details see:
https://bugzilla.gnome.org/show_bug.cgi?id=783145
https://bugzilla.gnome.org/show_bug.cgi?id=774134