1

I'm using cairo to draw some circular widget like this.

I used "draw" event of drawing area to draw all of the widget, but i don't know how to update data in the widget. This is the code that i make:

gboolean hald_circular_gauge (GtkWidget *widget,cairo_t *cr, gdouble max, gdouble min, gdouble value, gchar *pcname ,gchar *unit){

cairo_text_extents_t extents, extentsTemp, extentsLabel, extentsTempMin, extentsTempMax;
  int width, height;
  gint percentage, linewidth;
  double x,y;
  gdouble declive = (360.0-180.0)/(max-min);
  gdouble origin = 180.0 - declive*min;
  gchar pcTemp[BUFSIZ];

  width = gtk_widget_get_allocated_width (widget);
  height = gtk_widget_get_allocated_height (widget);



  double angle1 = 180.0  * (M_PI/180.0);  /* angles are specified */
  double angle2 = 360.0 * (M_PI/180.0);  /* in radians           */

  if(min > value || value >max)
      return FALSE;

  linewidth = (MIN (width, height) / 2.0 * 30.0) / 100.0;

  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6);
  cairo_set_line_width (cr, linewidth);
  cairo_arc(cr, width/2.0, height/2.0,  MIN (width, height) / 2.0 - linewidth, angle1, angle2);
  cairo_stroke (cr);

  cairo_set_source_rgba (cr, 0.0, 0.9, 0.0, 1.0);
  cairo_set_line_width (cr, linewidth);
  cairo_arc(cr, width/2.0, height/2.0, MIN (width, height) / 2.0  - linewidth, 180.0  * (M_PI/180.0),(declive*value+origin)  * (M_PI/180.0) );
  cairo_stroke (cr);

  cairo_select_font_face (cr, "Roboto Thin", CAIRO_FONT_SLANT_NORMAL,
          CAIRO_FONT_WEIGHT_NORMAL);
  cairo_set_font_size (cr, linewidth);
  cairo_set_source_rgb (cr, 1.0, 1.0, 1);
  cairo_text_extents (cr, unit, &extents);
  x = width/2.0-(extents.width/2 + extents.x_bearing);
  y = height/2.0 - (extents.height/2 );
  cairo_move_to (cr, x, y);
  cairo_show_text (cr, unit);

  cairo_select_font_face (cr, "Roboto", CAIRO_FONT_SLANT_NORMAL,
              CAIRO_FONT_WEIGHT_BOLD);
  cairo_set_font_size (cr, linewidth*1.3);
  sprintf(pcTemp,"%.1f",value);
  cairo_text_extents (cr, pcTemp, &extentsTemp);
      x = width/2.0-(extentsTemp.width/2 + extentsTemp.x_bearing);
      y = height/2.0 - extentsTemp.y_bearing;
  cairo_move_to (cr, x, y);
  cairo_show_text (cr, pcTemp);

  cairo_select_font_face (cr, "Roboto Thin", CAIRO_FONT_SLANT_NORMAL,
                  CAIRO_FONT_WEIGHT_NORMAL);
  cairo_set_font_size (cr, linewidth);
  cairo_text_extents (cr, pcname, &extentsLabel);
      x = width/2.0-(extentsLabel.width/2 + extentsLabel.x_bearing);
      y = height/2.0 - extentsTemp.y_bearing  - extentsLabel.y_bearing*1.20;
  cairo_move_to (cr, x, y);
  cairo_show_text (cr, pcname);


  cairo_select_font_face (cr, "Roboto Thin", CAIRO_FONT_SLANT_NORMAL,
                      CAIRO_FONT_WEIGHT_NORMAL);
  cairo_set_font_size (cr, linewidth*0.5);
  sprintf(pcTemp,"%.1f",min);
  cairo_text_extents (cr, pcTemp, &extentsTempMin);
      x = width/2.0  - MIN (width, height) / 2.0 + linewidth - (extentsTempMin.width/2 + extentsTempMin.x_bearing);
      y = height/2.0 - extentsTempMin.y_bearing*1.20;
  cairo_move_to (cr, x, y);
  cairo_show_text (cr, pcTemp);


  cairo_select_font_face (cr, "Roboto Thin", CAIRO_FONT_SLANT_NORMAL,
                      CAIRO_FONT_WEIGHT_NORMAL);
      cairo_set_font_size (cr, linewidth*0.5);
      sprintf(pcTemp,"%.1f",max);
      cairo_text_extents (cr, pcTemp, &extentsTempMax);
          x = width/2.0  + MIN (width, height) / 2.0 - linewidth + (-extentsTempMax.width/2 + extentsTempMax.x_bearing);
          y = height/2.0 - extentsTempMax.y_bearing*1.20;
      cairo_move_to (cr, x, y);
      cairo_show_text (cr, pcTemp);
    return TRUE;
 }

and the result is this

 GtkWidget *drawing_area = gtk_drawing_area_new ();
     gtk_widget_set_size_request (drawing_area, 100, 100);
     gtk_box_pack_start (GTK_BOX(gtk_builder_get_object(builder, "box30")),drawing_area,FALSE,TRUE,0);

I create a drawing area and request the size, but i don't get this size. So my question are:

  • How can i update data inside a drawing area (generate a draw event??)?

  • Why i can't request a size of the drawing area widget?

Opinions are welcome.

R. Rodrigues
  • 55
  • 10

1 Answers1

2

Answer to

1) Everytime you update data, force a draw update with:

gtk_widget_queue_draw(GTK_WIDGET(drawing_area))

2) You can request a size but if the container is set to expand, then the widget can eventually expand; the set_size_request function/method will set the minimum size the drawing area will "have". From what we can see on your code, the drawing area is inside a GtkBox. Check the expand and fill flags.

Tip 1: You can test the set_size_request by using your drawing_area inside a GtkFixed container

Tip 2: Try to create a custom widget, it would be a better solution.

José Fonte
  • 4,016
  • 2
  • 16
  • 28
  • Thanks! The problem is that my scroll window is set to expand, and i thought that don't causes any problem. To redraw i need to send some data, like i send in draw event, how can i make in draw update?? – R. Rodrigues Jun 22 '17 at 08:45
  • Do you have any example how to create a simple custom widget with cairo? – R. Rodrigues Jun 22 '17 at 08:46
  • @R.Rodrigues You must have the values that the drawing_area represents outside the draw callback. Let's say you have the percentage. Now, somewhere in your business logic, you need to update that value, so you do percentage = x, then you can issue a gtk_widget_queue_draw and the draw method will take that value and redraw to the actual new value. There is a lot of information scattered on the internet about creating custom gtk widgets. Most are for Gtk2. Check [this for c++](https://developer.gnome.org/gtkmm-tutorial/stable/sec-custom-widgets.html.en) – José Fonte Jun 22 '17 at 10:23
  • @R.Rodrigues or [this for Gtk2/C](http://zetcode.com/gui/gtk2/customwidget/) and [also this](http://djcj.org/gtk/) or [this in Vala](https://github.com/phastmike/vala-circular-progress-bar) – José Fonte Jun 22 '17 at 10:31
  • Yes, i see for gtk2 but not for gtk3.. and this one is for c++ not c :( – R. Rodrigues Jun 22 '17 at 10:32
  • C custom widgets get quite verbose, take the last vala example and generate the C code and continue from there. Anyway, that is another question. Feel free to ask more questions. Boa sorte – José Fonte Jun 22 '17 at 10:35
  • Thanks for helping! – R. Rodrigues Jun 22 '17 at 11:04
  • Do you now how to update this code http://zetcode.com/gui/gtk2/customwidget/ to GTK3? I'm sorry, but i can't open another question.. – R. Rodrigues Jun 22 '17 at 11:33
  • @R.Rodrigues Check [this one instead](http://djcj.org/gtk/code/) I think its Gtk3 already (At least the author claims it to be, haven't looked though). – José Fonte Jun 22 '17 at 11:36
  • 1
    Thanks, it works! Now i will see if i understand and make my custom widget. Obrigado! – R. Rodrigues Jun 23 '17 at 09:08