2
votes

I'm using gtk+-3.2.4 on Ubuntu 11.04 (Natty). I'm trying to draw in a GtkDrawingArea with Cairo and have the drawing area be scrollable. The code runs without errors but no drawing is done. What am I doing wrong ?

// gcc -Wextra -o scrol `pkg-config --cflags --libs gtk+-3.0` scrol1.c

#include <gtk/gtk.h>

#define WINDOW_WIDTH  800
#define WINDOW_HEIGHT 600

static gboolean draw_cb (GtkWidget *widget, GdkEventExpose *event) 
{
  cairo_t *cr;
  cr = gdk_cairo_create (gtk_widget_get_window (widget));
  cairo_set_source_rgb(cr, 1, 1, 1);
  cairo_paint(cr);
  cairo_set_source_rgb (cr, 0.42, 0.65, 0.80);
  cairo_set_line_width (cr,6);
  cairo_rectangle (cr, 3, 3, 100, 100);
  cairo_stroke (cr); 
  cairo_destroy(cr);
  return FALSE;
}

int main (int argc, char *argv[])
{
  gtk_init (&argc, &argv);
  GtkWidget *window;
  GtkWidget *grid;
  GtkWidget *swindow;
  GtkWidget *viewport;
  GtkWidget *darea;

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  grid = gtk_grid_new();
  swindow = gtk_scrolled_window_new (NULL,NULL);
  viewport = gtk_viewport_new (NULL,NULL);
  darea = gtk_drawing_area_new();

  gtk_container_add (GTK_CONTAINER(viewport), darea);
  gtk_container_add (GTK_CONTAINER(swindow), viewport);
  gtk_grid_attach (GTK_GRID(grid), swindow, 0, 1, 1, 2);
  gtk_container_add (GTK_CONTAINER(window), grid);

  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
  g_signal_connect (darea, "draw", G_CALLBACK(draw_cb),  NULL);

  gtk_widget_show_all (window);
  gtk_main ();
  return 0;
  }
5
What exactly do you mean with "but no drawing is done"? What do you see on screen?Uli Schlachter
I just get a grey window. It should have a blue rectangle on a white background.mike

5 Answers

3
votes

Here's a screenshot of the window that your code creates:

Screenshot of window

I imagine that you were expecting to see a square. However, all that you get to see is the top left of that square. This is because the drawing area has requested a very small amount of space, resulting in a small window. This means that your wonderful artwork is being clipped to fit in a window of this minimal size. There are a couple of things you could do:

  1. Set the minimum size of the scrolled window that contains the drawing area:

    gtk_widget_set_size_request( swindow, 500, 500 );
    

    This will result in a 500 by 500 pixel drawing area being visible (which is lots more than you need for the square). However, if you make the window larger, then the drawing area will not fill it.

  2. Set the scrolled window to take on all horizontal and vertical space it can get:

    gtk_widget_set_hexpand( swindow, TRUE );
    gtk_widget_set_vexpand( swindow, TRUE );
    

    If you just do this, then the window will initially look the same as the one in your original code. However, if you manually resize the window, then you'll see that the scrolled window (and hence the drawing area) expands to fill all of the space it can in the window. If you expand it enough, you'll see your square.

If you combine both of the above, then you'll get a window that's initially ~500x500 pixels. If you resize it, then the drawing area will expand to fill the window.

You could also add a gtk_widget_set_size_request call to set the size of the drawing area widget. If you set it to be larger than the scrolled window's size, then you'll get scrollbars.

2
votes

The drawing is done, however it's just in the top-left corner of the window. I added the following two calls and everything looks fine to me:

gtk_widget_set_hexpand(GTK_WIDGET(swindow), TRUE);  
gtk_widget_set_vexpand(GTK_WIDGET(swindow), TRUE);
1
votes

Try returning TRUE from the on_draw() callback to block the default handler; perhaps the default handler is drawing empty space over your drawing?

0
votes
// gcc -Wextra -o grid1 `pkg-config --cflags --libs gtk+-3.0` grid1.c

#include <gtk/gtk.h>

#define WINDOW_WIDTH  200
#define WINDOW_HEIGHT 80

static gboolean draw_cb (GtkWidget *widget, GdkEventExpose *event) 
{
  cairo_t *cr;
  cr = gdk_cairo_create (gtk_widget_get_window (widget));
  cairo_set_source_rgb(cr, 1, 1, 1);
  cairo_paint(cr);
  cairo_set_source_rgb (cr, 0.42, 0.65, 0.80);
  cairo_set_line_width (cr,6);
  cairo_rectangle (cr, 3, 3, 400, 100);
  cairo_stroke (cr);
  cairo_destroy(cr);
  return TRUE;
}

int main (int argc, char *argv[])
{
  gtk_init (&argc, &argv);
  GtkWidget *window;
  GtkWidget *grid;
  GtkWidget *swindow;
  GtkWidget *viewport;
  GtkWidget *darea;

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  grid = gtk_grid_new();
  swindow = gtk_scrolled_window_new (NULL,NULL);
  viewport = gtk_viewport_new (NULL,NULL);
  darea = gtk_drawing_area_new();

  gtk_widget_set_size_request (window, 200, 100);
  gtk_widget_set_size_request (darea, 406, 106);

  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
                                  GTK_POLICY_ALWAYS,
                                  GTK_POLICY_NEVER);

  gtk_widget_set_hexpand(GTK_WIDGET(swindow), TRUE);  
  gtk_widget_set_vexpand(GTK_WIDGET(swindow), TRUE);

  gtk_container_add (GTK_CONTAINER(viewport), darea);
  gtk_container_add (GTK_CONTAINER(swindow), viewport);
  gtk_grid_attach (GTK_GRID(grid), swindow, 0, 0, 1, 1);                 
  gtk_container_add (GTK_CONTAINER(window), grid);

  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
  g_signal_connect (darea, "draw", G_CALLBACK(draw_cb),  NULL);

  gtk_widget_show_all (window);
  gtk_main ();
  return 0;
  }