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.
Related
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 created a filechooser dialog in Glade. I placed OK and Cancel buttons in it. After that I set the clicked handler of the GtkButton to be open_clicked or whatever; also I have a button which displays the filechooser dialog. Its signal handler is cb_show_filed. Here is my code:
#include <gtk/gtk.h>
typedef struct _Data Data;
struct _Data
{
GtkWidget *file;
};
G_MODULE_EXPORT void cb_show_filed(GtkButton *button, Data *data)
{
gtk_dialog_run(GTK_DIALOG(data->file));
gtk_widget_hide(data->file);
}
int main(int argc, char **argv)
{
GtkBuilder *builder;
GtkWidget *window;
GtkWidget *filechooserdialog1;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "ui.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
filechooser =
GTK_WIDGET(gtk_builder_get_object(builder, "filechooserdialog1"));
gtk_builder_connect_signals(builder, &data);
g_object_unref(G_OBJECT(builder));
gtk_widget_show(window);
gtk_main();
return (0);
}
Now, how can I get path and filename from filechooserdialog1?
Use gtk_file_chooser_get_file() and friends:
GFile *chosen_file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(filechooser));
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..
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);
}