Printing value of entry box in a dialog in gtk c - c

I have worked recently with gtk+ in c language.
I have tried to communicate between two callbacks in a dialog and not in the main window (like here). But, unlike the solutions in the link, the program crushes (in the second callback when I try to use the widget I get from the parameters).
This is my code for This:
#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
static void print_text (GtkWidget *widget, gpointer data)
{
GtkEntry* entry = data;
printf("%s", gtk_entry_get_text(entry));
}
static void open_dialog (GtkWidget *widget, gpointer data)
{
GtkWidget *window = data;
GtkWidget *dialog;
GtkWidget *content_area;
GtkWidget *grid;
GtkWidget *label;
GtkWidget *button;
static GtkEntry *textbox;
dialog = gtk_dialog_new_with_buttons ("Get Text",
window,
GTK_DIALOG_MODAL,
GTK_STOCK_OK,
GTK_RESPONSE_OK,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
grid = gtk_grid_new();
gtk_container_add (GTK_CONTAINER (content_area), grid);
label = gtk_label_new("Value: ");
gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
textbox = gtk_entry_new();
gtk_entry_set_text(textbox, "<Value>");
gtk_grid_attach(GTK_GRID(grid), textbox, 1, 0, 1, 1);
gtk_widget_show_all (dialog);
g_signal_connect (GTK_DIALOG (dialog), "response", G_CALLBACK (print_text), textbox);
}
static void activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *entry;
GtkWidget *grid;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
button = gtk_button_new_with_label ("Print Text");
g_signal_connect (button, "clicked", G_CALLBACK (open_dialog), window);
gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1);
gtk_widget_show_all (window);
}
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;
}
The program should have printed the value of the entry box which in the dialog after closing the dialog. Note: in the main window there is a button that opens the dialog.
Thanks for helping!

Problem is on the print_text function. The prototype for GtkDialog response signal is:
void user_function (GtkDialog *dialog,
gint response_id,
gpointer user_data)
So you must change your function to:
static void print_text (GtkWidget *widget, gint response_id, gpointer data)
{
GtkEntry* entry = data;
printf("%s", gtk_entry_get_text(entry));
gtk_widget_destroy (widget); // This will close the dialog
}

Related

Java Swing "pack" - GTK Equivalent

I have for example this code:
#include <gtk/gtk.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("foo.bar", 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;
}
It looks like this:
How can I automatically resize the window, so it has the perfect size for the one button.
With Java Swing, you could simply call pack(), but I wasn't able to find a similar method for GTK.
For GtkWindow there would be gtk_window_resize, but it requires giving an height and width, so I would have to calculate it manually.
This would work with just one button, but anything more complex would be error-prone and prone to failure.
Is there any equivalent to pack?

Ignore keyboard cursor in GTK3 C

Using GTK3 in C, I have an interface with buttons. I want a user with a mouse to be able to press a button OR use press a single button on the keyboard to do the same thing.
MWE (modified from GTK3 Hello World example):
/*
* Ignore keyboard cursor in GTK3 C
*/
#include <gtk/gtk.h>
void thing() {
printf("did a thing\n");
}
void otherthing() {
printf("did something different\n");
}
static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
gchar* val = gdk_keyval_name (event->keyval);
if (strcmp(val, "Left") == 0) {
thing();
}
return 0;
}
static void activate (GtkApplication *app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button;
GtkWidget *button2;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Do the thing");
button2 = gtk_button_new_with_label ("xxx");
g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
g_signal_connect (button, "clicked", G_CALLBACK (thing), window);
g_signal_connect (button2, "clicked", G_CALLBACK (otherthing), window);
gtk_container_add (GTK_CONTAINER (button_box), button2);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
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;
}
In this program, the user can press the left arrow key to execute thing. The user can also click on the gui button to execute thing. However, hitting certain keyboard keys such as space or enter will "click" on the gui button to execute thing.
How do I prevent the keyboard from "clicking" on a button which the keyboard cursor is on in this case?
Fake Button Hack
I have hacked a workaround into my code for now using a useless button. I will not be marking this answer as solved since it is very sloppy, but it does the job until something better becomes available.
Description
This hack adds another button with no functions assigned. Using gtk_widget_grab_focus, we force this useless "fakebutton" to hold keyboard focus. We reissue this command every time a button is pressed.
Problems
Grabbing focus back to the fakebutton is slow. The user can issue a quick succession of commands (in the case of the MWE by pressing Left and Space to erroneously issue the otherthing function).
MWE
/*
* Ignore keyboard cursor in GTK3 C
*/
#include <gtk/gtk.h>
GtkWidget *fakebutton;
void thing() {
printf("did a thing\n");
}
void otherthing() {
printf("did something different\n");
}
static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
gchar* val = gdk_keyval_name (event->keyval);
if (strcmp(val, "Left") == 0) {
thing();
gtk_widget_grab_focus(fakebutton);
} else {
gtk_widget_grab_focus(fakebutton);
}
return 0;
}
static void activate (GtkApplication *app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button;
GtkWidget *button2;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Do the thing");
button2 = gtk_button_new_with_label ("xxx");
fakebutton = gtk_button_new();
g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
g_signal_connect (button, "clicked", G_CALLBACK (thing), window);
g_signal_connect (button2, "clicked", G_CALLBACK (otherthing), window);
gtk_container_add (GTK_CONTAINER (button_box), button2);
gtk_container_add (GTK_CONTAINER (button_box), fakebutton);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
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;
}

How to add css style context providers for all labels in a grid?

I am trying to set the background color of all labels in GtkGrid. Here is a simplified example:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label1 = gtk_label_new("Hello world!");
gtk_widget_set_hexpand( label1, TRUE);
gtk_grid_attach(GTK_GRID (grid), label1, 0,0,1,1);
GtkWidget *label2 = gtk_label_new("Simple Gtk example");
gtk_widget_set_hexpand( label2, TRUE);
gtk_grid_attach(GTK_GRID (grid), label2, 0,1,1,1);
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (
provider, "label {background-color: #AAAAAA;}", -1, NULL);
GtkStyleContext *context = gtk_widget_get_style_context (grid);
gtk_style_context_add_provider(
context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new(
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
However, adding the style context provider to the grid's context (as shown above) does not work.
I've modified your code, this will change the background of the labels:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label1 = gtk_label_new("Hello world!");
gtk_widget_set_hexpand( label1, TRUE);
gtk_grid_attach(GTK_GRID (grid), label1, 0,0,1,1);
GtkWidget *label2 = gtk_label_new("Simple Gtk example");
gtk_widget_set_hexpand( label2, TRUE);
gtk_grid_attach(GTK_GRID (grid), label2, 0,1,1,1);
GtkCssProvider *provider = gtk_css_provider_new ();
GdkDisplay *display = gdk_display_get_default();
GdkScreen *screen = gdk_display_get_default_screen (display);
gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_css_provider_load_from_data (
provider, "GtkLabel { background-color: #AAAAAA;}", -1, NULL);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new(
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
Result:

GtkEntry manipulation

I'm trying to make a small program to manipilate data between GtkEntry fields. To do this I'm using global variables. But using g_print functions to show me the contents I get NULL data! What is wrong in my way?
#include <gtk/gtk.h>
const gchar *entry0_text;
const gchar *entry1_text;
const gchar *entry2_text;
static void my_function (GtkWidget *widget, GtkWidget *entry)
{
g_print ("Entry0 contents: %s\n", gtk_entry_get_text (GTK_ENTRY (entry)));
g_print ("Entry1 contents: %s\n", *entry0_text);
g_print ("Entry2 contents: %s\n", *entry1_text);
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
GtkWidget *entry0;
GtkWidget *entry1;
GtkWidget *entry2;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), ":-)");
gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (grid));
entry0 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry0, 0, 0, 1, 1);
entry0_text = gtk_entry_get_text (GTK_ENTRY (entry0));
entry1 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry1, 1, 0, 1, 1);
entry1_text = gtk_entry_get_text (GTK_ENTRY (entry1));
entry2 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry2, 0, 1, 1, 1);
entry2_text = gtk_entry_get_text (GTK_ENTRY (entry2));
button = gtk_button_new ();
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
g_signal_connect (button, "clicked", G_CALLBACK (my_function), entry0);
gtk_widget_show_all (window);
}
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'm using Debian GNU/Linux and compiling with a script like this:
gcc pkg-config --libs --cflags gtk+-3.0 -o $2 $1
Thank You!
The values for entry0_text - entry2.text are retrieved during the startup of your program. But since there has been no entry made yet, they contain empty strings.
You have to use gtk_entry_get_text for all of your entry widgets inside the callback function my_function, not inside the activate function.
Besides that, you are using the second and third g_print incorrectly; you should use
g_print ("Entry1 contents: %s\n", entry1_text);
g_print ("Entry2 contents: %s\n", entry2_text);
Remember that after your program has started, entry1_text and entry2_text contain empty strings. But with *entry1_text and *entry2_text you won't receive the empty string, but the first element of this string, which is the terminating '\0' null character, this is why you receive a 'null' for these g_prints. So use entry1_text instead of *entry1_text.
The following code is working properly; I've used the entry widgets and strings as global variables for simplicity.
#include <gtk/gtk.h>
#include <string.h>
GtkWidget *entry0;
GtkWidget *entry1;
GtkWidget *entry2;
const gchar *entry0_text;
const gchar *entry1_text;
const gchar *entry2_text;
static void my_function (void)
{
entry0_text = gtk_entry_get_text (GTK_ENTRY (entry0));
entry1_text = gtk_entry_get_text (GTK_ENTRY (entry1));
entry2_text = gtk_entry_get_text (GTK_ENTRY (entry2));
g_print ("Entry0 contents: %s\n", entry0_text);
g_print ("Entry1 contents: %s\n", entry1_text);
g_print ("Entry2 contents: %s\n", entry2_text);
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), ":-)");
gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (grid));
entry0 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry0, 0, 0, 1, 1);
entry1 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry1, 1, 0, 1, 1);
entry2 = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry2, 0, 1, 1, 1);
button = gtk_button_new ();
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
g_signal_connect (button, "clicked", G_CALLBACK (my_function), NULL);
gtk_widget_show_all (window);
}
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;
}

Drag and drop, motion_notify_event, mouse coordinate shaking

Then i start to drag an icon (code below), it starts jumping between 2 positions.
Can anybody help me resolve this shaking problem ?
Code:
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <string.h>
#define ICON_BUFFER 5
struct Icon {
GtkWidget *image;
int x,y,width,height;
};
GtkWidget *window;
GtkWidget *fixed;
struct Icon icons[ICON_BUFFER];
gboolean drag = FALSE;
static gboolean handleMove( GtkWidget *widget, GdkEventButton *event, gpointer data ){
struct Icon *icon = (struct Icon*) data;
icon->x = (int)event->x;
icon->y = (int)event->y;
gtk_fixed_move (GTK_FIXED (fixed), widget, icon->x, icon->y);
printf("move (%d , %d) %d\n", icon->x, icon->y,event->time);
return TRUE;
}
static gboolean handleRelease( GtkWidget *widget, GdkEventButton *event, gpointer data ){
g_signal_handlers_disconnect_by_func(widget, handleMove, data);
printf("%s\n", "disconnect_handleMove");
struct Icon *icon = (struct Icon*) data;
printf("position (%d , %d)\n", icon->x, icon->y);
drag = FALSE;
return TRUE;
}
static gboolean handleClick( GtkWidget *widget, GdkEventButton *event, gpointer data ){
//g_print ("Event box clicked at coordinates %f,%f\n", event->x, event->y);
struct Icon *icon = (struct Icon*) data;
if(!drag){
drag = TRUE;
printf("%s\n", "connect_handleMove");
g_signal_connect (G_OBJECT (widget), "motion_notify_event" ,G_CALLBACK(handleMove), data);
g_signal_connect (G_OBJECT (widget), "button-release-event",G_CALLBACK(handleRelease), data);
printf("position (%d , %d)\n", icon->x, icon->y);
return TRUE;
}else
return TRUE;
}
int main( int argc, char *argv[] ){
/* GtkWidget is the storage type for widgets */
GtkWidget *event;
GtkWidget *image;
GtkWidget *background;
GtkStyle *style;
GdkPixbuf *pixbuf;
gint i;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Fixed Container");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
fixed = gtk_fixed_new ();
gtk_container_add (GTK_CONTAINER (window), fixed);
gtk_widget_set_size_request(fixed,480,480);
gtk_widget_show (fixed);
for (i = 0 ; i < 4 ; i++) {
event = gtk_event_box_new ();
image = gtk_image_new_from_file("test2.jpg");
icons[i].image = image;
icons[i].x = i*50;
icons[i].y = i*50;
icons[i].width = 50;
icons[i].height = 50;
gtk_container_add (GTK_CONTAINER (event), image);
gtk_fixed_put (GTK_FIXED (fixed), event, i*50, i*50);
gtk_event_box_set_above_child(GTK_EVENT_BOX(event), FALSE);
g_signal_connect (G_OBJECT (event), "button_press_event",
G_CALLBACK (handleClick), (gpointer) &icons[i]);
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event),(gboolean)FALSE);
gtk_widget_show (image);
gtk_widget_show (event);
}
gtk_widget_show (window);
gtk_main ();
return 0;
}
Code can be compiled and run with (or gtk+-2.0 instead of gtk+-3.0):
cc pkg-config --cflags --libs gdk-pixbuf-2.0 gtk+-3.0 FixedDragAndDrop.c -o FixedDragAndDrop.o && ./FixedDragAndDrop.o

Resources