pass string from inputfield to function fails - GTK c-language - c

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!

Related

GTK3 resize attempt grows window exponentially

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.

Getting an error Xlib: extension "RANDR" missing on display ":24.0". gtk

I am receiving this error and not sure why...Please take a look at my buttons array, maybe I messed smth there, I am not sure...
The error i get is: Xlib: extension "RANDR" missing on display ":24.0".
and nothing happens after that, meaning my program doesnt run at all....
#include <gtk/gtk.h>
/* Our new improved callback. The data passed to this function
* is printed to stdout. */
static void callback (GtkWidget *widget, gpointer data)
{
system ((gchar *) data);
}
/* another callback */
static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_main_quit ();
return FALSE;
}
int main (int argc, char *argv[])
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window;
GtkWidget *box1;
/* This is called in all GTK applications. Arguments are parsed
* from the command line and are returned to the application. */
gtk_init (&argc, &argv);
/* Create a new window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/* This is a new call, which just sets the title of our
* new window to "My Assignments" */
gtk_window_set_title (GTK_WINDOW (window), "My Assignments");
/* Here we just set a handler for delete_event that immediately
* exits GTK. */
g_signal_connect (window, "delete-event",
G_CALLBACK (delete_event), NULL);
/* Sets the border width of the window. */
gtk_container_set_border_width (GTK_CONTAINER (window), 50);
/* We create a box to pack widgets into. This is described in detail
* in the "packing" section. The box is not really visible, it
* is just used as a tool to arrange widgets. */
box1 = gtk_vbox_new (FALSE,0);
/* Put the box into the main window. */
gtk_container_add (GTK_CONTAINER (window), box1);
/*array is here*/
GtkWidget *button[2];
int i;
for (i=0; i<2; i++)
{
button[i]=gtk_button_new();
}
button[0] = gtk_button_new_with_label ("Run shellscript");
g_signal_connect (button[0], "clicked",
G_CALLBACK (callback), "shellscript");
gtk_box_pack_start (GTK_BOX (box1), button[0], TRUE, TRUE, 0);
gtk_widget_show(button[0]);
button[1] = gtk_button_new_with_label ("Run program2 ");
g_signal_connect (button[1], "clicked",
G_CALLBACK (callback), "program");
gtk_box_pack_start (GTK_BOX (box1), button[1], TRUE, TRUE, 0);
gtk_widget_show(button[1]);
gtk_widget_show (box1);
/* Rest in gtk_main and wait for the fun to begin! */
gtk_main ();
return 0;
}

How to send multiple entrys to function - GTK

I have developed a financial calculator in c - Black & Scholes. My teacher wants me to implement a GUI to this and he suggested GTK. Due to my poor knowledge in c (java programmer from the start) this is almost too much for me at the moment because the deadline is in 4 hours. But after hard work and good help here on stackoverflow I think I have a chanche to make it!. But right now there is one irritating obstacle to overide -
That is to pass more than one entry to a method. In short - there are five inputfields and what I want is to send all these via g_signal_connect_swapped to a method where the invoked string i extracted. The thing is that I am able to do this (thanks to help) as long as there are only one string (one entry). But how do I send all these entrys to the function?
I have tried to declare a vector without success. It wont even compile due to errors.
static GtkWidget entry[5]
Since an array is a pointer (to the first element) it should work - but not!
And more strange - I had another idea - instead of sending the entrys I tried to extract the string value in the main-method - exaxtly the same syntax as in the function - but without succes. The value is null.
const gchar *text;
text = gtk_entry_get_text(GTK_ENTRY (entry_a));
printf ("Result: %s\n", text);
the above snippet works as expexted in the function - but not in the main-function. Why???
Hope you understand my question - here follows the code that generates the GUI. The code is without error - that is where I send ONE entry-value to the callback-function.
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
static GtkWidget *asset_label;
static GtkWidget *frame;
static GtkWidget *entry_a, *entry_s, *entry_v, *entry_t, *entry_r;
static GtkWidget *label_a, *label_s, *label_v, *label_t, *label_r;
static GtkWidget *window, *result_label, *button;
static GtkWidget *table;
static void entry_Submit(GtkWidget *entry, GtkWidget *widget) {
const gchar *text;
text = gtk_entry_get_text(GTK_ENTRY (entry_a));
printf ("Result: %s\n", text);
gtk_widget_destroy(GTK_WIDGET(label_a));
label_a = gtk_label_new (text);
gtk_grid_attach (GTK_GRID (table), label_a, 1, 0, 1, 1);
gtk_widget_show(label_a);
}
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);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (GTK_WIDGET (window), 300, 300);
gtk_window_set_title (GTK_WINDOW (window), "FINANCIAL CALCULATOR");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect_swapped (window, "delete-event", G_CALLBACK (gtk_widget_destroy), window);
/* Create a 1x2 table */
table = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), table);
//create a text box (asset price)
entry_a = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (table), entry_a, 0, 0, 1, 1);
// create a new label.
label_a = gtk_label_new (" ASSET PRICE" );
gtk_grid_attach (GTK_GRID (table), label_a, 1, 0, 1, 1);
//create a text box (strike price)
entry_s = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (table), entry_s, 0, 1, 1, 1);
// create a new label.
label_s = gtk_label_new (" STRIKE PRICE" );
gtk_grid_attach (GTK_GRID (table), label_s, 1, 1, 1, 1);
//create a text box (time to maturity)
entry_t = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (table), entry_t, 0, 2, 1, 1);
// create a new label.
label_t = gtk_label_new (" TIME TO MATURITY" );
gtk_grid_attach (GTK_GRID (table), label_t, 1, 2, 1, 1);
//create a text box (volatility)
entry_v = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (table), entry_v, 0, 3, 1, 1);
// create a new label.
label_v = gtk_label_new (" VOLATILITY" );
gtk_grid_attach (GTK_GRID (table), label_v, 1, 3, 1, 1);
//create a text box (interest rate)
entry_r = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (table), entry_r, 0, 4, 1, 1);
// create a new label.
label_r = gtk_label_new (" INTEREST RATE" );
gtk_grid_attach (GTK_GRID (table), label_r, 1, 4, 1, 1);
button = gtk_button_new_with_label("Calculate");
g_signal_connect_swapped (button, "clicked", G_CALLBACK (entry_Submit), entry_a);
gtk_grid_attach (GTK_GRID (table), button, 0, 5, 2, 1);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
these are the errors when I declare an array of GtkWidget
1) In the entry_submit callback-function () where I declare the following:
text = gtk_entry_get_text(GTK_ENTRY (entry[0]));
compile error: error: subscripted value is neither array nor pointer nor vector
2) In the main function where I declare the following:
entry[0] = gtk_entry_new ();
error: incompatible types when assigning to type 'GtkWidget' from type 'struct GtkWidget *'
A pointer to pointer is the answer and at the same to use malloc since I declare the GtkWidget in the main-function.
GtkWidget **entry;
entry = malloc(5 * sizeof(GtkWidget));
entry[0] = entry_a;
entry[1] = entry_s;
entry[2] = entry_t;
entry[3] = entry_v;
entry[4] = entry_r;
g_signal_connect_swapped (button, "clicked", G_CALLBACK (entry_Submit), entry);
and the function
static void entry_Submit(GtkWidget **entry, GtkWidget *widget) {
GtkWidget *entry_ptr_a = entry[0];
GtkWidget *entry_ptr_s = entry[1];
GtkWidget *entry_ptr_t = entry[2];
GtkWidget *entry_ptr_v = entry[3];
GtkWidget *entry_ptr_r = entry[4];
const gchar *a, *s, *t, *v, *r;
a = gtk_entry_get_text(GTK_ENTRY (entry_ptr_a));
s = gtk_entry_get_text(GTK_ENTRY (entry_ptr_s));
t = gtk_entry_get_text(GTK_ENTRY (entry_ptr_t));
v = gtk_entry_get_text(GTK_ENTRY (entry_ptr_v));
r = gtk_entry_get_text(GTK_ENTRY (entry_ptr_r));
printf ("Result: %s , %s, %s, %s, %s\n", a, s, t, v, r);
}

How to get the text of a button in GTK?

I am developing an application that has a numeric keypad and a text box when clicked on a button, text box shows the number.
I need to write a function to each button? Or you can pass a text and a widget as parameter?
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
void callback( GtkWidget *widget,
gpointer data )
{
gtk_entry_append_text(entry, text);
}
void create_button(GtkWidget* table,GtkWidget* entry,
int start_r,int end_r,
int start_c,int end_c,
char* label)
{
GtkWidget *button;
button = gtk_button_new_with_label (label);
g_object_set_data( G_OBJECT( button ),
"char", (gpointer)label );
g_signal_connect (button, "clicked",
G_CALLBACK (callback), entry);
gtk_table_attach_defaults (GTK_TABLE(table), button, start_c, end_c, start_r, end_r);
gtk_widget_show (button);
}
gint delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
gtk_main_quit ();
return(FALSE);
}
int main(int argc,char* argv[]){
GtkWidget *window;
//GtkWidget *button;
GtkWidget *table;
GtkWidget *entry;
//GtkWidget *label;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Armario");
g_signal_connect (GTK_OBJECT (window), "delete_event",
G_CALLBACK (delete_event), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
table = gtk_table_new (2, 2, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
entry = gtk_entry_new();
gtk_entry_set_max_length(GTK_ENTRY(entry),10);
gtk_entry_set_placeholder_text(GTK_ENTRY(entry),"Teste");
gtk_table_attach_defaults (GTK_TABLE(table), entry, 0, 2, 1, 2);
gtk_widget_show(entry);
create_button(table,entry,0,1,0,1,"Botao");
gtk_widget_show (table);
gtk_widget_show (window);
gtk_main ();
return 0;
}
The answer to your question is yes, you can pass a widget in Gtk+ to a callback. Actually, the first parameter of the callback for the clicked signal is the button which received the signal (ie. usually the button that was clicked). As you can see in the sample code below, you can extract from the button its label and use it as text.
[...] /* In create_button... */
/* Make your buttons be notified when they are clicked */
g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), entry);
[...]
/* Append the text in the button to the text entry */
void on_button_clicked (GtkButton *button, gpointer user_data)
{
GtkEntry *entry = user_data;
const gchar *text = gtk_button_get_label (button);
gint position = 0;
gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &position);
}
I'm using gtk_editable_insert_text because gtk_entry_append_text has been deprecated for a long time. Passing the "entry" parameter to the callback is possible by using the last parameter of g_signal_connect which allows you to specify some data that you need to access in your callback. This info is then made available to the callback in the "user_data" parameter.
Your exemple could also be improved by using gtk_widget_show_all, and I also don't see the point in calling g_object_set_data on the "char" property, as the text is already set in the label property (and retrieved with gtk_button_get_label).
Two options, that I can think of:
GTK widgets are really GObjects, so you can attach to them arbitrary pieces of data. See the functions g_object_set_data/g_object_set_data_full/g_object_get_data. So you can just add the text to the button as an attached data and retrieve it when needed.
You can pass any data you need to a callback by defining a struct with all the fields, and passing a pointer to it. If the struct cannot be declared statically, you can malloc it and use g_signal_connect_data to specify the function to release the data:
For example:
struct entry_and_text;
{
GtkWidget *w;
char *text;
};
void free_data(gpointer data, GClosure *closure)
{
free(data);
}
entry_and_text *data = (entry_and_text *)malloc(sizeof(entry_and_text));
data->w = entry;
data->text = label;
g_signal_connect_data (button, "clicked",
G_CALLBACK (callback), data, free_data, 0);

Textbox with a label in a GTK+ program

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.

Resources