gtkmm text on a picture - c++

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;
}

Related

GTK Maximizing a Form c++

I am using Ubuntu 20.04 and I have a small GTK 3.0 Form I am trying to get to maximize on first startup. I later want to get this into a Full GLADE project, but first I'm just trying to get this to maximize to full screen.
The commented sections are what I have tried to no avail.
Nothing works and it throws compiler errors, can anyone help me in my endeavor?
#include <gtk/gtk.h>
int main(int argc, char *argv[]) {
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Center");
// gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
// gtk_window_fullscreen(GTK_WINDOW(window);
// gtk_window_fullscreen(GtkWindow *window);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_show(window);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
Thank you.
Use gtk_window_maximize(GtkWindow *window):
#include <gtk/gtk.h>
int main(int argc, char *argv[]) {
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Center");
gtk_window_maximize(GTK_WINDOW(window));
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_show(window);
//...
}
Note that you can call it before showing the window. Doc:
Asks to maximize window , so that it becomes full-screen. Note that you shouldn’t assume the window is definitely maximized afterward, because other entities (e.g. the user or window manager) could unmaximize it again, and not all window managers support maximization. But normally the window will end up maximized. Just don’t write code that crashes if not.
It’s permitted to call this function before showing a window, in which case the window will be maximized when it appears onscreen initially.
You can track maximization via the “window-state-event” signal on GtkWidget, or by listening to notifications on the “is-maximized” property.
Suggestion: Use gtkmm with C++
Example with gtkmm:
#include <gtkmm.h>
int main(int argc, char *argv[])
{
auto app =
Gtk::Application::create(argc, argv,
"org.gtkmm.maximize.base");
Gtk::Window window;
window.maximize();
return app->run(window);
}

gtk_window_set_icon_from_file() not working properly

I'm trying to display my icon in my window's title bar. The program compiles and runs fine, but the icon is only being displayed in the launcher.
Here's my main function:
int main(int argc, char * argv[])
{
GtkWidget * window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "My Window");
gtk_window_set_default_size(GTK_WINDOW(window), 600, 600);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_icon_from_file(GTK_WINDOW(window), "img/icon.png", NULL);
gtk_widget_show(window);
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
Thanks in advance for any help.
The documentation for gtk_window_set_icon() and friends says,
This icon is used when the window is minimized (also known as iconified). Some window managers or desktop environments may also place it in the window frame, or display it in other contexts.
So it not required that the icon is displayed in the title bar; that is at the discretion of the window manager in your desktop environment. The default window managers in both Gnome and Unity currently do not do so.

gtk - Image not showing when loaded from file

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.

GTK Entry to Integer conversion

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.

Get text from Textbox in GTK+

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.