I'm currently creating a GUI that has buttons to delete and create a grid each time to simulate going to the next or previous page. The first time I go to the next page it works fine and returns me the string of the window's title.
However, once I attempt to go back to the previous page,
char *titles = gtk_window_get_title(GTK_WINDOW(window))
prints out (null) and a segmentation fault occurs. I have also tried changing the title to static but to no avail.
I am using
if (strcmp(titles, PgOne) == 0) to check which page the user is currently on so the program knows the subsequent page to create.
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
char *PgTwo = "Page 2";
char *PgOne = "Page 1";
static void NewCallback(GtkWidget *grid, gpointer user_data)
{
GtkWidget *gridNew;
GtkWidget *window;
GtkWidget *button;
gridNew = gtk_grid_new();
window = gtk_widget_get_toplevel(grid);
gtk_widget_destroy(grid);
char *titles = gtk_window_get_title(GTK_WINDOW(window));
if (strcmp(titles, PgTwo) == 0)
{
gtk_window_set_title(GTK_WINDOW(window), "Page 1");
gtk_container_add(GTK_CONTAINER(window), gridNew);
button = gtk_button_new_with_label("Next Page");
g_signal_connect_swapped(button, "clicked", G_CALLBACK(NewCallback), grid);
/* Place the button in the grid cell (0, 1), and make it fill Span 2 columns */
gtk_grid_attach(GTK_GRID(grid), button, 0, 1, 2, 1);
button = gtk_button_new_with_label("Quit");
g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), window);
/* Place the Quit button in the grid cell (0, 2), and make it Span 2 columns. */
gtk_grid_attach(GTK_GRID(grid), button, 0, 2, 2, 1);
}
else if (strcmp(titles, PgOne) == 0)
{
gtk_window_set_title(GTK_WINDOW(window), "Page 2");
gtk_container_add(GTK_CONTAINER(window), gridNew);
button = gtk_button_new_with_label("Back to Main Menu");
g_signal_connect_swapped(button, "clicked", G_CALLBACK(NewCallback), grid);
/* Place the Quit button in the grid cell (0, 2), and make it Span 2 columns. */
gtk_grid_attach(GTK_GRID(gridNew), button, 0, 1, 2, 1);
}
// Recursive show all items in window
gtk_widget_show_all(window);
}
static void activate(GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
/* create a new window, and set its title */
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Page 1");
gtk_container_set_border_width(GTK_CONTAINER(window), 100);
/* Here we construct the container that is going pack our buttons */
grid = gtk_grid_new();
/* Pack the container in the window */
gtk_container_add(GTK_CONTAINER(window), grid);
button = gtk_button_new_with_label("Next Page");
g_signal_connect_swapped(button, "clicked", G_CALLBACK(NewCallback), grid);
/* Place the button in the grid cell (0, 1), and make it fill Span 2 columns */
gtk_grid_attach(GTK_GRID(grid), button, 0, 1, 2, 1);
button = gtk_button_new_with_label("Quit");
g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), window);
/* Place the Quit button in the grid cell (0, 2), and make it Span 2 columns. */
gtk_grid_attach(GTK_GRID(grid), button, 0, 2, 2, 1);
// Recursive show all items in window
gtk_widget_show_all(window);
}
// Main function is here
int main(int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
I solved this by changing the variable grid to gridNew as I have already called gtk_widget_destroy(grid) prior.
g_signal_connect_swapped(button, "clicked", G_CALLBACK(NewCallback), gridNew);
Tried to accept my solution but tells me to wait 2 days before accepting it
Related
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.
I had the following code and I want to change the value of the label "title" when I press te button "hlpBtn" but I have troubles with it.
#include <gtk/gtk.h>
void button_clicked(GtkWidget *widget, gpointer data)
{
GtkWidget *title = (GtkWidget *) data;
title = gtk_label_new("DECODED!!");
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *table;
GtkWidget *title;
GtkWidget *wins;
GtkWidget *halign;
GtkWidget *halign2;
GtkWidget *hlpBtn;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request (window, 650, 850);
gtk_window_set_title(GTK_WINDOW(window), "Windows");
gtk_container_set_border_width(GTK_CONTAINER(window), 15);
table = gtk_table_new(6, 4, FALSE);
gtk_table_set_col_spacings(GTK_TABLE(table), 3);
gtk_table_set_row_spacing(GTK_TABLE(table), 0, 3);
title = gtk_label_new("Decrypting code...");
halign = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), title);
gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1,
GTK_FILL, GTK_FILL, 0, 0);
halign2 = gtk_alignment_new(0, 1, 0, 0);
hlpBtn = gtk_button_new_with_label("RUN");
gtk_container_add(GTK_CONTAINER(halign2), hlpBtn);
gtk_widget_set_size_request(hlpBtn, 70, 30);
gtk_table_set_row_spacing(GTK_TABLE(table), 3, 5);
gtk_table_attach(GTK_TABLE(table), halign2, 0, 1, 4, 5,
GTK_FILL, GTK_FILL, 0, 0);
g_signal_connect(G_OBJECT(hlpBtn), "clicked",
G_CALLBACK(button_clicked), title);
gtk_container_add(GTK_CONTAINER(window), table);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), G_OBJECT(window));
gtk_widget_show_all(window);
gtk_main();
return 0;
}
My intention is to call the funcition button_clicked when I press hlpBtn and then changue title from "Decrypting code..." to "DECODED!!".
What is wrong here?
Thank you.
Why don't you do something like this, instead of creating a new label?
void button_clicked(GtkWidget *widget, gpointer data)
{
gtk_label_set_text((GtkLabel *)data, "DECODED!!");
}
What's wrong with your code: you take a pointer to an existing label, make a local copy of it, create a new label and overwrite the local pointer with the pointer to the new item. The problem is, overwriting the pointer does by no mean replace the original item within the window. You would need to destroy the existing label and then add the new instance. But as you can see from my code, the solution is much easier than that: just update the existing label with the new content.
I have one issue with gtk in c . I tried to follow the tutorial but I am not able to pass a text-entry to a function when one clicks on the button in the widget.
The code compiles fine but when I press the button I get several warnings and the string from text-entry that was supposed to be printed are null
What did I do wrong?
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
static GtkWidget *asset_label;
static GtkWidget *frame;
static GtkWidget *entry;
static void entry_Submit(GtkWidget *widget, GtkWidget *entry)
{
const gchar *text = gtk_entry_get_text(GTK_ENTRY (entry));
printf ("Result: %s\n", text);
gtk_widget_destroy(GTK_WIDGET(asset_label));
asset_label = gtk_label_new (text);
gtk_container_add (GTK_CONTAINER (frame), asset_label);
gtk_widget_show_all(frame);
}
static void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
}
static void initialize_window(GtkWidget* window)
{
gtk_window_set_title(GTK_WINDOW(window),"My Window"); //Set window title
gtk_window_set_default_size (GTK_WINDOW (window), 400, 200); //Set default size for the window
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL); //End application when close button clicked
}
int main (int argc, char *argv[])
{
GtkWidget *window,*table,*label, *button;
gtk_init(&argc, &argv);
//Create the main window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
initialize_window(window);
/* Create a 1x2 table */
table = gtk_table_new (3, 3, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
/* create a new label. */
label = gtk_label_new ("Enter some text:" );
//gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
gtk_table_set_homogeneous(GTK_TABLE (table), TRUE);
gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 0, 1);
//create a text box
entry = gtk_entry_new ();
//gtk_entry_set_text (GTK_ENTRY (entry), "");
gtk_entry_set_max_length (GTK_ENTRY (entry),0);
gtk_table_attach_defaults (GTK_TABLE (table), entry, 0, 1, 0, 1);
button = gtk_button_new_with_label("Calculate");
g_signal_connect_swapped (button, "clicked", G_CALLBACK (entry_Submit), entry);
gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2);
//gtk_widget_show (button);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
And when the button is clicked I get this result:
Result: (null)
There is a problem in the callback or the way you are registering the callback (as fixing either one of them should fix your problem).
By default the clicked callback takes GtkButton as the first parameter and gpointer data as the second. By using g_signal_connect_swapped you are saying that in the callback function, the parameters will be swapped i.e., the first parameter will be gpointer data (GtkEntry in your code) and second GtkButton. But in your callback function you are treating second parameter entry which is in fact GtkButton as GtkEntry. Either use g_signal_connect instead of g_signal_connect_swapped or use the first parameter widget as GtkEntry in your callback function.
Side note: Regarding the warning, if the code which you have posted is the full code then in the callback function entry_Submit during first execution asset_label is null and thus gtk_widget_destroy(GTK_WIDGET(asset_label)); will throw a warning. Also, frame is unassigned before use in the callback function.
Hope this helps!
I have a gtk_window which contain 4 buttons.
One of these buttons will open a file selection dialog (another function) which - when the file has been choosed - will show up a dialog with 3 gtk_entry (this function).
static void function_with_3_gtk_entry (gchar *message, gpointer mainwin){
GtkWidget *dialog, *label, *content_area, *entry1, *entry2, *entry3;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons ("Nome File", mainwin, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
entry1 = gtk_entry_new();
entry2 = gtk_entry_new();
entry3 = gtk_entry_new();
gtk_widget_set_size_request(dialog, 250, 200);
/* Ensure that the dialog box is destroyed when the user responds */
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
/* Add the label, and show everything we've added to the dialog */
gtk_container_add (GTK_CONTAINER (content_area), entry1);
gtk_container_add (GTK_CONTAINER (content_area), entry2);
gtk_container_add (GTK_CONTAINER (content_area), entry3);
gtk_widget_show_all (dialog);
}
My questions are:
can i use another gtk_window into this function instead of a gtk_dialog?
how can i set the dialog not resizable?
The code snippet below has two functions:
create_dialog() creates a dialog which cannot be resized, as requested.
create_window() creates a window, within a function, as requested.
Hope this helps.
#include <gtk/gtk.h>
/* Create a dialog, which cannot be resized by the user. */
void create_dialog(GtkWidget *button, gpointer window) {
GtkWidget *dialog, *label, *content_area;
/* New label for dialog content */
label = gtk_label_new("This is a dialog!");
/* Make a new dialog with an 'OK' button */
dialog = gtk_dialog_new_with_buttons("This is a dialog, which (shouldn't | can't) be resized!", window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);
/* Add label to dialog */
content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
gtk_container_add(GTK_CONTAINER(content_area), label);
/* Destroy dialog properly */
g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
/* Set dialog to not resize. */
gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
gtk_widget_show_all(dialog);
}
/* Create a window, while in a function! */
void create_window(GtkWidget *button, gpointer window) {
GtkWidget *new_window, *label;
/*New label for dialog content */
label = gtk_label_new("This is a window, created in a function!");
/* Create new window */
new_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/* Add label to window */
gtk_container_add(GTK_CONTAINER(new_window), label);
gtk_widget_show_all(new_window);
}
/* Boring implementation bits */
gint main(gint argc, char **argv) {
/* Initialise GTK+ */
gtk_init(&argc, &argv);
GtkWidget *main_win, *dialog_button, *window_button, *button_container;
/* Create a button, one for each function. */
dialog_button = gtk_button_new_with_label("Create dialog!");
window_button = gtk_button_new_with_label("Create window!");
/* Pack buttons into a box. */
button_container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start(GTK_BOX(button_container), dialog_button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(button_container), window_button, FALSE, FALSE, 0);
/* Connect signals to button callback functions */
g_signal_connect(dialog_button, "clicked", G_CALLBACK(create_dialog), main_win);
g_signal_connect(window_button, "clicked", G_CALLBACK(create_window), main_win);
/* Create a new window, show it, and run GTK+ */
main_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(main_win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_container_add(GTK_CONTAINER(main_win), button_container);
gtk_widget_show_all(main_win);
gtk_main();
return 0;
}
I am new to GTK+ programming.I wrote a simple GTK+ program where i display a label and a textbox in a window, the label should be to the left of the textbox and i should be able to specify the horizontal length of the textbox. Below is my code so far,the program runs fine but im unable to align the label to the left of the textbox and also set the textbox horizontal length.
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
static void destroy(GtkWidget *widget,gpointer data)
{
gtk_main_quit ();
}
int main (int argc, char *argv[])
{
GtkWidget *window,*table,*label,*entry;
gtk_init(&argc, &argv);
void initialize_window(GtkWidget *);
//Create the main window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
initialize_window(window);
gtk_widget_show(window);
/* Create a 1x2 table */
table = gtk_table_new (1, 2, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
gtk_widget_show (table);
/* create a new label. */
label = gtk_label_new ("Enter some text: ");
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
gtk_table_attach_defaults (GTK_TABLE (table),label, 0, 1, 0, 1);
gtk_widget_show (label);
//create a text box
entry = gtk_entry_new ();
gtk_entry_set_max_length (GTK_ENTRY (entry),0);
gtk_table_attach_defaults (GTK_TABLE (table),entry, 0, 1, 0, 1);
gtk_widget_show (entry);
gtk_main ();
return 0;
}
void initialize_window(GtkWidget *window)
{
gtk_window_set_title(GTK_WINDOW(window),"My Window"); //Set window title
gtk_window_set_default_size (GTK_WINDOW (window), 400, 200); //Set default size for the window
g_signal_connect (window, "destroy",G_CALLBACK (destroy), NULL); //End application when close button clicked
}
How can i fix this problem ?
Please help
Thank You.
You messed with the table position and don't set aligin if you do not know what it does, it may be a bit missleading.
Here is working code (I think this is what you wanted):
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
static void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
}
static void initialize_window(GtkWidget* window)
{
gtk_window_set_title(GTK_WINDOW(window),"My Window"); //Set window title
gtk_window_set_default_size (GTK_WINDOW (window), 400, 200); //Set default size for the window
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL); //End application when close button clicked
}
int main (int argc, char *argv[])
{
GtkWidget *window,*table,*label,*entry;
gtk_init(&argc, &argv);
//Create the main window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
initialize_window(window);
/* Create a 1x2 table */
table = gtk_table_new (1, 2, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
/* create a new label. */
label = gtk_label_new ("Enter some text:" );
//gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
gtk_table_set_homogeneous(GTK_TABLE (table), TRUE);
gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 0, 1);
//create a text box
entry = gtk_entry_new ();
gtk_entry_set_max_length (GTK_ENTRY (entry),0);
gtk_table_attach_defaults (GTK_TABLE (table), entry, 0, 1, 0, 1);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
For alignment one can use hbox for horizontal arrangement or vbox for vertical arrangement.