I am having some trouble drawing images with gtk2. I have tried this code:
#include <gtk/gtk.h>
static gboolean button_press_callback (GtkWidget *event_box, GdkEventButton *event, gpointer data)
{
g_print ("Event box clicked at coordinates %f,%f\n",
event->x, event->y);
/* Returning TRUE means we handled the event, so the signal
* emission should be stopped (don't call any further
* callbacks that may be connected). Return FALSE
* to continue invoking callbacks.
*/
return TRUE;
}
static GtkWidget*
create_image (void)
{
GtkWidget *image;
GtkWidget *event_box;
image = gtk_image_new_from_file ("image.png");
}
int main(int argc, char const *argv[])
{
create_image();
return 0;
}
It will not draw any images onscreen, infact I don`t see any window at all. Also, what is the best way to store an image in a variable for future use?
I suggest you to look at the gtk tutorial https://developer.gnome.org/gtk-tutorial/stable/, a lot of things are missing for your code to display here a sample on how to display a simple picture in a window :
#include <gtk/gtk.h>
GtkWidget* create_gui()
{
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL); // create the application window
GtkWidget *img = gtk_image_new_from_file("image.png"); // image shall be in the same dir
gtk_container_add(GTK_CONTAINER(win), img); // add the image to the window
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(gtk_main_quit), NULL); // end the application if user close the window
return win;
}
int main(int argc, char** argv) {
GtkWidget* win;
gtk_init(&argc, &argv);
win = create_gui();
gtk_widget_show_all(win); // display the window
gtk_main(); // start the event loop
return 0;
}
BTW, gtk 2 is no longer being maintained, I suggest you start with gtk3 if you can
Related
I'm trying to use cairo to draw some arcs but gcc warns me that gdk_cairo_create() is deprecated. Use gdk_window_begin_draw_frame() and gdk_drawing_context_get_cairo_context() instead.
To get around this I did some research and found out that for gdk_window_begin_draw_frame() I need "GdkWindow".I've always been using GtkWidget for my windows so I need to convert "GtkWidget" to "GdkWindow", but gtk_widget_get_window() returns NULL and causes segfault.
#include <gtk/gtk.h>
#include <cairo.h>
void main(int argc , char **argv){
gtk_init(&argc , &argv);
GtkWidget *win;
GdkWindow *gdkwin;
GdkDrawingContext *dc;
cairo_region_t *region;
cairo_t *cr;
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
region = cairo_region_create();
gdkwin = gtk_widget_get_window(GTK_WIDGET(win));
//Here gdkwin should contain a GdkWindow but it's NULL.
gc = gdk_window_begin_draw_frame(gdkwin , (const cairo_region_t*)®ion);
...
...
Here's the runtime errors:
(a.out:6852): Gdk-CRITICAL **: 23:53:06.042: gdk_window_begin_draw_frame: assertion 'GDK_IS_WINDOW (window)' failed
(a.out:6852): Gdk-CRITICAL **: 23:53:06.042: gdk_drawing_context_get_cairo_context: assertion 'GDK_IS_DRAWING_CONTEXT (context)' failed
Segmentation fault
I want to get a cairo object and use it for cairo_arc().
Thanks.Best regards.
The below is the complete source code to get Cairo working under GTK 3. It should be compilable as is.
As the others already pointed out, you have to use the draw signal to make things work.
#include <gtk/gtk.h>
#include <cairo.h>
// ------------------------------------------------------------
gboolean on_draw (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
// "convert" the G*t*kWidget to G*d*kWindow (no, it's not a GtkWindow!)
GdkWindow* window = gtk_widget_get_window(widget);
cairo_region_t * cairoRegion = cairo_region_create();
GdkDrawingContext * drawingContext;
drawingContext = gdk_window_begin_draw_frame (window,cairoRegion);
{
// say: "I want to start drawing"
cairo_t * cr = gdk_drawing_context_get_cairo_context (drawingContext);
{ // do your drawing
cairo_move_to(cr, 30, 30);
cairo_set_font_size(cr,15);
cairo_show_text(cr, "hello world");
}
// say: "I'm finished drawing
gdk_window_end_draw_frame(window,drawingContext);
}
// cleanup
cairo_region_destroy(cairoRegion);
return FALSE;
}
// ------------------------------------------------------------
int main (int argc, char * argv[]) {
gtk_init(&argc, &argv);
GtkWindow * window;
{ // window setup
window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (window, 200, 200);
gtk_window_set_position (window, GTK_WIN_POS_CENTER);
gtk_window_set_title (window, "Drawing");
g_signal_connect(window, "destroy", gtk_main_quit, NULL);
}
// create the are we can draw in
GtkDrawingArea* drawingArea;
{
drawingArea = (GtkDrawingArea*) gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)drawingArea);
g_signal_connect((GtkWidget*)drawingArea, "draw", G_CALLBACK(on_draw), NULL);
}
gtk_widget_show_all ((GtkWidget*)window);
gtk_main();
return 0;
}
// ------------------------------------------------------------
In GTK+ 3, you're supposed to do your drawing in response to the draw signal. Doing it in the main makes no sense (the widgets have just been created, but initializing them further in done when running the main event loop).
Please read: https://developer.gnome.org/gtk3/stable/chap-drawing-model.html
The Dark Trick's program is complete.
He uses the functions as follows,
GdkWindow* window = gtk_widget_get_window (widget);
cairo_region_t *cairoRegion = cairo_region_create();
GdkDrawingContext *drawingContext;
drawingContext = gdk_window_begin_draw_frame (window, cairoRegion);
cairo_t *cr = gdk_drawing_context_get_cairo_context (drawingContext);
But I am using the the functions as follows,
GdkWindow *window = gtk_widget_get_window(widget);
cairo_rectangle_int_t cairoRectangle = {0, 0, 200, 200};
cairo_region_t *cairoRegion = cairo_region_create_rectangle (&cairoRectangle);
GdkDrawingContext *drawingContext;
drawingContext = gdk_window_begin_draw_frame (window,cairoRegion);
cairo_t *cr = gdk_drawing_context_get_cairo_context (drawingContext);
This worked, but I can not understand the differencies, for I am an OldUrologist.
I'm not positive, but I think you're trying to get the GdkWindow before it is ready. I think you need to connect to the window's "realize" signal, and only when that signal has been emitted should you try to access the underlying GdkWindow.
#include <gtk/gtk.h>
#include <cairo.h>
void OnWindowRealize(GtkWidget *pWidget, gpointer data)
{
GdkWindow *pUnderlyingWindow = gtk_widget_get_window(pWidget);
cairo_region_t *region = cairo_region_create();
GdkDrawingContext *gc = gdk_window_begin_draw_frame(pUnderlyingWindow, (const cairo_region_t*)®ion);
//etc...
}
void main(int argc , char **argv)
{
gtk_init(&argc , &argv);
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(win), "realize", OnWindowRealize, NULL);
//etc...
}
#include <gtk/gtk.h>
GtkBuilder *builder;
GtkWidget *window;
GtkImage *image;
GtkButton *but;
char s[1000];
void on_button1_button_press_event(GtkWidget *but, gpointer data)
{
strcpy(s, "/home/linux/testing2.png");
gtk_widget_queue_draw (image);
}
int main(void)
{
gtk_init(NULL, NULL);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "/home/linux/gui.xml", NULL);
window = (GtkWidget *) gtk_builder_get_object(builder, "window1");
image = (GtkImage *) gtk_builder_get_object(builder, "image1");
but = (GtkButton *) gtk_builder_get_object(builder, "button1");
gtk_image_set_from_file(image, strcpy(s, "/home/linux/testing1.png"));
g_signal_connect(but, "clicked", G_CALLBACK(on_button1_button_press_event), NULL);
gtk_widget_show(window);
gtk_main();
return 0;
}
When I click on "button1", "callback" function called, and it updates string s then I want gtk refresh "image1" with gtk_widget_queue_draw. But "image1" have not changed.
gtk_widget_queue_draw() takes a string with the filename of the image. But it does not keep the string you pass. Instead the widget stores the whole loaded image.
So your s variable is useless, and changing it does nothing. You should do instead, in main():
gtk_image_set_from_file(image, "/home/linux/testing1.png");
and in the event callback:
gtk_image_set_from_file(image, "/home/linux/testing2.png");
There is no need to call gtk_widget_queue_draw() because changing the image does that automatically.
I have been scratching my head on Why is below code triggers on-draw callback three times as opposed to just once.
#include <iostream>
#include <gtk/gtk.h>
using namespace std;
void on_draw(){
cout << "drawing"<<endl;
}
int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *drgArea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
drgArea = gtk_drawing_area_new();
// gtk_widget_set_redraw_on_allocate(drgArea, -1);
gtk_container_add(GTK_CONTAINER(window), drgArea);
gtk_widget_show_all(window);
g_signal_connect(drgArea, "expose-event",
G_CALLBACK(on_draw), NULL);
gtk_main();
return 0;
}
This is probably related to your compositor/window manager.
Using cinnamon [2.0.14] shows 2 redraws when starting up the application (no matter if I use gtk3/3.10.6/"draw" or gtk2/2.24.22/"expose-event").
I am trying to determine the size of a maximized window so I can set the window size to a value close to it. However, I don't know how to do that without first showing the maximized window. Is there a way to emit the signal generated by gtk_window_maximize before the window is displayed?
Below is my attempt so far. The problem is that I can see a flash of the maximized window before the resizing takes place.
#include <gtk/gtk.h>
int signal_id;
void resize(GtkWindow *window, GdkEvent *event, gpointer data)
{
gint width, height;
g_signal_handler_disconnect(G_OBJECT(window), signal_id);
gtk_window_get_size(window, &width, &height);
gtk_window_resize(window, width - 10, height - 10);
}
int main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
signal_id = g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(resize), NULL);
gtk_window_maximize(GTK_WINDOW(window));
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
No it is not possible, because until the window manager maps the window, the actual size is not known. But what you can do is get the screen size:
width=gdk_screen_width();
height=gdk_screen_height();
gtk_widget_set_size_request(window, width/2, height/2);
This question already has an answer here:
save current window as image using gtk#
(1 answer)
Closed 4 years ago.
This is a piece of code which creates a window:
#include <gtk/gtk.h>
static GtkWidget* createWindow()
{
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
gtk_widget_set_name(window, "GtkLauncher");
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
return window;
}
int main(int argc, char* argv[])
{
GtkWidget *main_window;
gtk_init(&argc, &argv);
if (!g_thread_supported())
g_thread_init(NULL);
main_window = createWindow();
gtk_widget_grab_focus(main_window);
gtk_widget_show_all(main_window);
gtk_main();
return 0;
}
And in here: Convert a GTK python script to C , i got how to take a screenshot.
gdk_get_default_root_window() will give me the screenshot of the desktop.
gdk_screen_get_active_window (gdk_screen_get_default()) will give me the screenshot of any active window.
Is there any way to take the screenshot of the window being created in the code above??
I think this should do it, although you may need to iterate the main loop after showing the window to get it to paint properly, in which case you'll need some more code (I haven't tested this)
#include <unistd.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <cairo.h>
static GtkWidget* createWindow()
{
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
gtk_widget_set_name(window, "GtkLauncher");
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
return window;
}
int main(int argc, char **argv)
{
gdk_init(&argc, &argv);
GtkWidget *main_window = createWindow();
gtk_widget_show_all(main_window);
// may not need this, it also may not be enough either
while (gtk_events_pending ()) gtk_main_iteration ();
GdkWindow *w = GDK_WINDOW(main_window);
gint width, height;
gdk_drawable_get_size(GDK_DRAWABLE(w), &width, &height);
GdkPixbuf *pb = gdk_pixbuf_get_from_drawable(NULL,
GDK_DRAWABLE(w),
NULL,
0,0,0,0,width,height);
if(pb != NULL) {
gdk_pixbuf_save(pb, "screenshot.png", "png", NULL);
g_print("Screenshot saved to screenshot.png.\n");
} else {
g_print("Unable to get the screenshot.\n");
}
return 0;
}
If it doesn't work you'll have to move the screenshot taking into an event handler that connects to some event (I'm not sure which probably window-state-event then you have to look at the event to figure out when to take the screenshot)