How do you get the text from a gtk entry widget and then convert that to an integer value. Notice in my code I include a wrapper struct called Window that contains pointers to widgets. In the main, I declare an instance of a Window and then build the correct widgets with the appropriate GTK function calls. I then pass that window object to the function that handles the clicked action. I want to then calculate the numerator divided by the denominator in integer format. Below is my attempt. All the code works except for the button_clicked function. Any ideas?
#include <gtk/gtk.h>
#include <stdlib.h>
struct Window
{
GtkWidget *numerator;
GtkWidget *denominator;
GtkWidget *button;
GtkWidget *label;
};
void button_clicked(GtkWidget *widget, gpointer data)
{
Window* w = (Window*)data;
char buf[10];
char buffer[200];
GtkEntry* e = (GtkEntry*)w->numerator;
const gchar* entry1 = gtk_entry_get_text(e);
char* test = (char*)gchar;
int r = atoi(test);
sprintf(buf,"%d",r);
GtkWidget *label = w->label;
gtk_label_set_text(GTK_LABEL(label), buf);
}
int main(int argc, char*argv[])
{
GtkWidget *window;
GtkWidget *table;
Window w;
//Set up my window
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Division");
gtk_window_set_default_size(GTK_WINDOW(window),500,500);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
//Create my table and add it to the window
table = gtk_table_new(4,2,FALSE);
gtk_container_add(GTK_CONTAINER(window),table);
//Create instances of all my widgets
w.numerator = gtk_entry_new();
w.denominator = gtk_entry_new();
w.button = gtk_button_new_with_label("Click");
w.label = gtk_label_new("result");
//Attack the widgets to the table
gtk_table_attach(GTK_TABLE(table), w.numerator,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
gtk_table_attach(GTK_TABLE(table), w.denominator,0,1,1,2,GTK_FILL,GTK_FILL,5,5);
gtk_table_attach(GTK_TABLE(table), w.button,0,1,2,3,GTK_FILL,GTK_FILL,5,5);
gtk_table_attach(GTK_TABLE(table), w.label,0,1,3,4,GTK_FILL,GTK_FILL,5,5);
//attach the click action to with the button to invoke the button_clicked function
g_signal_connect(G_OBJECT(w.button),"clicked",G_CALLBACK(button_clicked),&w);
g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
If I see this correctly, in your "test code" all you're trying to do is set the label string to the contents of "w->numerator", right?
The line
char* test = (char*)gchar;
looks fishy to me and doesn't even compile, it looks like a typo.
Change the "gchar" to "entry1", and it should do what you want it to.
I have a recommendation for you though: use GtkSpinButton instead of GtkEntry. It is like a custom Entry made for numerical values, and the retrieval of such is many times easier.
Related
I'd like to have a picture element in my gui with text on it. My goal is to load pictures (for example a waterdrop) and place text on it which stands for a measured humidity (values come from MQTT).
What would be the best way to do this? I don't care if it's a label or any other kind of element (though I'm not happy with misusing a button for that). The text needs to be changable. Im very new to this framework so I didn't get the hang on it yet.
Thank you!
This is an example code. It uses an overlay to stack two widgets, an image and a label:
#include <gtk/gtk.h>
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *image;
GtkWidget *label;
GtkWidget *overlay;
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_title(GTK_WINDOW(window), "Sandbox");
image = gtk_image_new_from_file("image.png");
label = gtk_label_new("I've always been too lame\n\
To see what's before me\n\
And I know nothing sweeter than\n\
Champaign from last New Years\n\
Sweet music in my ears\n\
And a night full of no fears\n\
\n\
But if I had one wish fulfilled tonight\n\
I'd ask for the sun to never rise\n\
If God passed a mic to me to speak\n\
I'd say \"Stay in bed, world,\n\
Sleep in peace");
overlay = gtk_overlay_new ();
gtk_container_add(GTK_CONTAINER(window), overlay);
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), image);
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), label);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I have a simple gtk window with one image in it. After making some modification on that image (taken from OpenCV) I want to make window refresh by expose-event. I use gtk2 and it is not possible to change to gtk3. There is no errors but image is not redrawn, the old one still persist.
class TestApp {
public:
GtkWidget *frameWindow;
GInputStream *inStr;
GtkWidget *image;
GdkPixbuf *pixBuff;
cv::Mat *frame;
TestApp(int argc, char *argv[]) : frameWindow(NULL), image(NULL), pixBuff(NULL), inStr(NULL),frame(NULL){
gtk_init(&argc, &argv);
}
int refresh(cv::Mat *f){
frame=f;
int sz = f->dataend - f->datastart;
memcpy((uchar*)gdk_pixbuf_get_pixels(pixBuff),f->datastart,sz);
gtk_widget_queue_draw(frameWindow);
return 0;
}
void imshow(cv::Mat *im){
/* main window */
frame = im;
frameWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width(GTK_CONTAINER(frameWindow), 1);
gtk_window_set_title(GTK_WINDOW(frameWindow), "image");
gtk_window_set_default_size(GTK_WINDOW(frameWindow), 1280, 720);
gtk_window_set_position(GTK_WINDOW(frameWindow), GTK_WIN_POS_CENTER);
gtk_window_fullscreen(GTK_WINDOW(frameWindow));
pixBuff=gdk_pixbuf_new_from_data((guchar*)im->datastart,GDK_COLORSPACE_RGB,FALSE,8,im->size().width,im->size().height,(im->channels()*im->cols), NULL,NULL);
image = gtk_image_new_from_pixbuf(pixBuff);
gtk_container_add(GTK_CONTAINER(frameWindow), image);
g_object_ref_sink(G_OBJECT(frameWindow));
g_signal_connect(G_OBJECT(frameWindow), "expose_event", G_CALLBACK((void*)exposeCb), (gpointer)this);
g_signal_connect(G_OBJECT(frameWindow), "key_press_event", G_CALLBACK((void*)buttonCb), (gpointer)this);
gtk_widget_realize(frameWindow);
gtk_widget_show_all(frameWindow);
gtk_main();
}
static gboolean buttonCb(GtkWidget *eventBox, GdkEventKey *event, gpointer data){
char c = event->keyval;
switch(c){
case 'q':
gtk_widget_destroy(eventBox);
gtk_main_quit();
break;
}
return true;
}
static gboolean exposeCb(GtkWidget *eventBox, GtkWidget *event, gpointer data){
return false;
}
};
int main (int argc, char *argv[]) {
TestApp gtkObj(argc,argv);
cv::Mat im=cv::imread("colour256.png");
cv::Mat imOld=im.clone();
cv::cvtColor(im,im,CV_BGR2RGB);
gtkObj.imshow(&im);
gtkObj.refresh(&imOld);
return 0;
}
Should I redraw image somehow?
FALSE is correct return value. Returning TRUE means "I have dealt with this event" so no further callbacks for particular event ("signal" in GTK+ parlance) are called, in particular default callback is not called so window is not painted. Returning FALSE doesn't stop other callbacks.
I don't think there's much difference. Id' leave it in refresh in order to avoid doing too much work in callbacks.
Quoted warning means that pointer passed to gtk_widget_queue_draw does not contain a GtkWidget. Maybe it hot corrupt? Maybe refresh is called prior to imshow?
I am a newbie at GTK+. I want to create a GUI with an Image with 2 buttons and a label below it.
The image has to be loaded via a file dialog which is opened when I click a button called "Load", but the image is not being shown on the Window. Below is my code:
#include <gtk/gtk.h>
#include <gtkmm.h>
#include <glib.h>
#include <cstring>
#include <cstdlib>
#include "cv.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
GtkWidget *window, *image;
GtkWidget *vbox, *valign, *hbox, *halign;
GtkWidget *expression_label;
char* get_file()
{
GtkWidget *dialog = gtk_file_chooser_dialog_new("Open File", (GtkWindow *) window, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
gtk_widget_destroy(dialog);
return filename;
}
}
void load_file(GtkWidget *widget, gpointer data)
{
g_print("Loading file\n");
char *file = get_file();
Mat img = imread(file);
//imshow("Opencv image", img);
image = gtk_image_new_from_file(file);
gtk_widget_queue_draw(image);
// gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
gtk_label_set_text(GTK_LABEL(expression_label), "Image Loaded");
g_print("File Loaded\n");
g_print("%s\n", file);
}
void get_expression(GtkWidget *widget, gpointer data)
{
gtk_label_set_text(GTK_LABEL(expression_label), "Expression Detected");
}
int main(int argc, char* argv[])
{
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "FEAR");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 1100, 1100);
gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
vbox = gtk_vbox_new(FALSE, 5);
hbox = gtk_hbox_new(TRUE, 3);
GtkWidget *load_button = gtk_button_new_with_label("Load");
GtkWidget *run_button = gtk_button_new_with_label("Run");
gtk_widget_set_size_request(load_button, 70, 30);
gtk_widget_set_size_request(run_button, 70, 30);
gtk_container_add(GTK_CONTAINER(hbox), load_button);
gtk_container_add(GTK_CONTAINER(hbox), run_button);
expression_label = gtk_label_new("Expression");
//image = gtk_image_new();
//Display placeholder image
image = gtk_image_new_from_file("../sample.jpg");
gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), expression_label, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
int load_handler_id = g_signal_connect(G_OBJECT(load_button), "clicked", G_CALLBACK(load_file), NULL);
g_signal_connect(G_OBJECT(run_button), "clicked", G_CALLBACK(get_expression), NULL);
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I basically created a main window, then added a vbox to it. In the vbox, I have added the image widget, a hbox box that holds by buttons and a label widget to give me relevant information.
When I run the program, it displays the placeholder image properly, but when I select "Load" and choose the new image to be displayed, the label changes and I get the correct output on the command line, but the image widget does not display the new image that was selected.
Can someone please help me and let me know what am I doing wrong?
You're getting a new GtkImage widget after loading, and that widget is never added to a window so (of course) it's not being displayed.
You're just overwriting a global widget pointer with the new widget, but that doesn't magically make the new widget "replace" the old in the widget hierarchy. That you store the pointer to the new widget in the variable that used to hold the old widget doesn't matter from GTK+'s perspective.
Replace your call to gtk_image_new_from_file() with a call to gtk_image_set_from_file() on your existing widget (in image) to replace the content of the existing widget, which is packed and so on, with the image from the file.
Also, you're leaking the filename, you need to add free() after using it.
UPDATE: You mention in a comment that you've made the filename a global, to make it available in more places. If so, you still need to free() the old filename before getting a new one, else your code will be leaking memory.
Here is my code:
#include <gtk/gtk.h>
G_MODULE_EXPORT void waka(GtkWidget *button, GtkWidget* entry1)
{
printf("%s",gtk_entry_get_text(GTK_ENTRY(entry1)));
}
int main(int argc, char * argv[])
{
GtkWidget *window, *button, *entry;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("hha");
g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(waka),entry);
entry = gtk_entry_new();
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE,2);
gtk_box_pack_start_defaults(GTK_BOX(vbox),button);
gtk_box_pack_start_defaults(GTK_BOX(vbox),entry);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
When I launch it, and try to fill in some string in the entry box, and then click the button, it said 'segmentation fault'. What is going on?
Also, the callback only works with one user data argument. How about if I want two or more arguments, what must I do in the callback function, and in the call to g_signal_connect()?
the problem is that you're trying to use pointer to entry before initializing it. I've changed a bit your code to fix this, see if it will work for you:
#include <gtk/gtk.h>
void waka(GtkWidget *button, GtkWidget* entry1)
{
g_print("entry: %s\n", gtk_entry_get_text(GTK_ENTRY(entry1)));
}
int main(int argc, char * argv[])
{
GtkWidget *window, *button, *entry, *vbox;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("hha");
entry = gtk_entry_new();
vbox = gtk_vbox_new(FALSE, 2);
gtk_box_pack_start_defaults(GTK_BOX(vbox),button);
gtk_box_pack_start_defaults(GTK_BOX(vbox),entry);
gtk_container_add(GTK_CONTAINER(window),vbox);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(waka), entry);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
hope this helps, regards
I'm trying to get the input text from a text box in a callback function when the user changes something it it (on "changed").
The code goes as follow:
#include <stdio.h>
#include <gtk/gtk.h>
void enter_callback( GtkWidget *widget, GtkEditable *buffer)
{
printf("%s",gtk_editable_get_chars(buffer, 0, -1));
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *text;
GtkWidget *table;
gtk_init (&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
table = gtk_table_new (2, 2, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
text=gtk_text_new(NULL, NULL);
gtk_text_set_editable(text, TRUE);
gtk_signal_connect(GTK_OBJECT(text), "changed", GTK_SIGNAL_FUNC(enter_callback), (GtkEditable*)text);
gtk_table_attach_defaults(GTK_TABLE(table), text, 0, 1, 0, 1);
gtk_container_border_width (GTK_CONTAINER (window), 40);
gtk_window_set_default_size (GTK_WINDOW(window), 640, 200);
gtk_widget_show(text);
gtk_widget_show(window);
gtk_widget_show(table);
gtk_main();
return 0;
}
The code compiles just right, I'm compiling it on Code::Blocks on debug, checking output on the console by printf. The problem is I get <NULL> as a callback everytime I change something on the textbox. How can I get the correct output?
SOLUTION:
As noted by Washu, gtk_text is deprecated and gtk_text_view should be used instead.
According to the GTK documentation, GtkText is deprecated, buggy, and should not be used. You should instead be using the GtkTextView widget via gtk_text_view_new.
You can use GtkEntry widget too. And use gtk_entry_get_text () (which return const gchar * value) that to get text from GtkEntry, for instance.