2017-06-21 8 views
0

J'utilise le cairo pour dessiner un widget circulaire comme this.Comment redessiner le texte avec le caire en utilisant gtk +

J'ai utilisé "dessiner" événement de la zone de dessin pour dessiner tous les widgets, mais je ne sais pas comment mettre à jour les données dans le widget. Ce est le code que je fais:

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

et le résultat est 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); 

Je crée une zone de dessin et demander la taille, mais je ne suis pas cette taille. Ma question sont:

  • Comment puis-je mettre à jour les données dans une zone de dessin (générer un événement de tirage ??)? Pourquoi est-ce que je ne peux pas demander une taille du widget de zone de dessin?

Les opinions sont les bienvenues.

Répondre

1

Réponse à

1) Chaque fois que vous mettez à jour les données, la force d'une mise à jour du tirage au sort avec:

gtk_widget_queue_draw(GTK_WIDGET(drawing_area)) 

2) Vous pouvez demander une taille mais si le conteneur est appelé à se développer, alors le widget peut éventuellement s'étendre; La fonction/méthode set_size_request définit la taille minimale que la zone de dessin aura ". De ce que nous pouvons voir sur votre code, la zone de dessin est à l'intérieur d'un GtkBox. Vérifiez les drapeaux d'expansion et de remplissage.

Astuce 1: Vous pouvez tester la set_size_request en utilisant votre drawing_area dans un conteneur GtkFixed

Astuce 2: Essayez de créer un widget personnalisé, ce serait une meilleure solution.

+0

Merci! Le problème est que ma fenêtre de défilement est définie pour se développer, et j'ai pensé que cela ne pose aucun problème. Pour redessiner j'ai besoin d'envoyer des données, comme je l'envoie dans l'événement de tirage, comment puis-je faire dans la mise à jour? –

+0

Avez-vous un exemple de création d'un widget personnalisé simple avec cairo? –

+0

@ R.Rodrigues Vous devez avoir les valeurs que la zone drawing_area représente en dehors du callback draw. Disons que vous avez le pourcentage. Maintenant, quelque part dans votre logique métier, vous devez mettre à jour cette valeur, donc vous faites percentage = x, puis vous pouvez émettre un gtk_widget_queue_draw et la méthode draw prendra cette valeur et redessinera la nouvelle valeur réelle. Il y a beaucoup d'informations éparpillées sur Internet à propos de la création de widgets gtk personnalisés. La plupart sont pour Gtk2. Vérifiez [ceci pour C++] (https://developer.gnome.org/gtkmm-tutorial/stable/sec-custom-widgets.html.en) –