繁体   English   中英

如何使用开罗和 Gtk3 在 GtkDrawingArea 中绘制一条线

[英]How to draw a line in a GtkDrawingArea using Cairo with Gtk3

可能有人请告诉我用C语言开罗Gtk3绘制的一条线的最小工作例子GtkDrawingArea 我试图修改testcairo.c测试文件夹中的 testcairo.c,但我无法让它工作。 请不要在开罗网站上推荐教程; Zetcode.com 或 gnome.org 要么不用于 Gtk3,要么不是最小的工作示例。

我知道了。 关键区别在于,对于 gtk+3,您必须从“绘制”信号处理程序中进行绘制。 使用 gtk+2,它来自“expose-event”信号处理程序。 这是一个最小的工作示例

这是一个完整的工作示例:

  • 确保gtk3-devel已安装(在 Fedora 中 #dnf install gtk3-devel)

  • 在 Ubuntu 中: sudo apt install libgtk-3-dev

编译: gcc draw.c `pkg-config --cflags gtk+-3.0 --libs gtk+-3.0` -o draw

#include <gtk/gtk.h>
gboolean draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
{
    guint width, height;
    GdkRGBA color;
    GtkStyleContext *context;
    
    context = gtk_widget_get_style_context (widget);
    width = gtk_widget_get_allocated_width (widget);
    height = gtk_widget_get_allocated_height (widget);
    gtk_render_background(context, cr, 0, 0, width, height);
    cairo_arc (cr, width/2.0, height/2.0, MIN (width, height) / 2.0, 0, 2 * G_PI);
    gtk_style_context_get_color (context, gtk_style_context_get_state (context), &color);
    gdk_cairo_set_source_rgba (cr, &color);
    gdk_cairo_set_source_rgba (cr, &color);
    cairo_fill (cr);
    return FALSE;
}

gint main(int argc,char *argv[])
{
    GtkWidget *window, *drawing_area;
    
    gtk_init (&argc, &argv);
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
    
    drawing_area = gtk_drawing_area_new();
    gtk_container_add (GTK_CONTAINER (window), drawing_area);
    gtk_widget_set_size_request (drawing_area, 200, 100);
    g_signal_connect (G_OBJECT (drawing_area), "draw", G_CALLBACK (draw_callback), NULL);
    gtk_widget_show_all (window);
    gtk_main ();
    return 0;
}

任何人都在 2020 年这样做。这是经过重构以与 GTK3 一起使用的 Zetcode 示例,它可以绘制您想要的内容,因此线条不会奇怪地连接。 我添加了评论来解释发生了什么。

/* To compile: gcc linetest.c -o linetest `pkg-config --cflags --libs gtk+-3.0`
* C program for basic drawing with GTK+ and cairo.
* Working 2020 example if this got you stuck, http://zetcode.com/gfx/cairo/basicdrawing/
* Note: the above command line uses backticks (`), it's right before 1 on your keyboard.
*/
#include <cairo.h>
#include <gtk/gtk.h>

//function prototypes
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data);
static void do_drawing(cairo_t *cr);
static gboolean clicked(GtkWidget *widget, GdkEventButton *event, gpointer user_data);
//end of function prototypes

/* Global variables for storing mouse coordinates,
* count is index of arrays, coordx and coordy are x and y coordinates of the mouse
*/
struct {
  int count;
  double coordx[100];
  double coordy[100];
} glob;

/* Function: on_draw_event
*Parameters: GtkWidget, cairo_t, gpointer
*Use: This is the function we attach to the main method when we want to draw. It calls the do_drawing method.
*Example: g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
*/
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
  do_drawing(cr);
  return FALSE;
}


/* Function: do_drawing
*Parameters: cairo_t
*Use: It sets cairo canvas settings, and draws shapes with a for loop
*Settings: are commented
*Note: printf is used during debugging to find mouse click coordinates :)
*/
static void do_drawing(cairo_t *cr)
{
  cairo_set_source_rgb(cr, 0, 0, 0);//Line colour
  cairo_set_line_width(cr, 0.5);//Line width

  if (glob.count > 1) {
    cairo_move_to(cr, glob.coordx[0], glob.coordy[0]);
    //printf("from: x:%f, y:%f\n",glob.coordx[0],glob.coordy[0]);
  }

  //Connect lines.
  for (int i = 1; i < glob.count; ++i) {
    cairo_line_to(cr, glob.coordx[i], glob.coordy[i]);
    //printf("to: x:%f, y:%f\n",glob.coordx[i],glob.coordy[i]);
  }

  // Draw the above.
  cairo_stroke(cr);
  //resets array so shape can be drawn again.
  glob.count = 0;
}


/* Function: clicked
*Parameters: GtkWidget, GdkEventButton, gpointer
*Use: Registers mouse clicks, 1 is right, 3 is left on laptop. Clicks may be 1, 2 or 3 on a desktop
*Note: printf is used during debugging to find mouse click coordinates :)
*/
static gboolean clicked(GtkWidget *widget, GdkEventButton *event,
  gpointer user_data)
{
  if (event->button == 1) {
       // printf("Right Click");
    glob.coordx[glob.count] = event->x;
    glob.coordy[glob.count++] = event->y;

        // int i;
        // for (i =0; i <= glob.count-1; i++) {
        //   printf("%f\n", glob.coordx[i]);
        // }
  }

  if (event->button == 3) {
        //printf("left Click");
    gtk_widget_queue_draw(widget);
  }

  return TRUE;
}

//Main method.
int main(int argc, char *argv[])
{
  //widget variables, window and drawing area.
  GtkWidget *window;
  GtkWidget *darea;

  //Set global count 0, so array is at beginning whenver program starts.
  glob.count = 0;

  //Always have this to start GTK.
  gtk_init(&argc, &argv);

  //Set new window, set new drawing area.
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  darea = gtk_drawing_area_new();

  //Add the drawing area to the window.
  gtk_container_add(GTK_CONTAINER(window), darea);

  //You need this to register mouse clicks.
  gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);

  //Attaching draw function to the main method.
  g_signal_connect(G_OBJECT(darea), "draw",
    G_CALLBACK(on_draw_event), NULL);

  //You can close window when you exit button.
  g_signal_connect(window, "destroy",
    G_CALLBACK(gtk_main_quit), NULL);

  //Register if left or right mouse click.
  g_signal_connect(window, "button-press-event",
    G_CALLBACK(clicked), NULL);

  //Set window position, default size, and title.
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
  gtk_window_set_title(GTK_WINDOW(window), "Lines");

  //Show all widgets.
  gtk_widget_show_all(window);

  //start window
  gtk_main();

  return 0;
}
// compila con valac --pkg gtk+-3.0 nombre_archivo.gs
uses 
    Gtk
    Cairo

init
    Gtk.init (ref args)
    var TestCairo = new Ventana ()
    TestCairo.show_all ()
    Gtk.main ()

class Ventana : Window

    area: Gtk.DrawingArea   

    init        
        title = "Test Genie + GTK + Cairo"
        set_default_size (400, 400)     
        window_position = WindowPosition.CENTER
        destroy.connect(Gtk.main_quit)

        // área de dibujo
        area: Gtk.DrawingArea = new Gtk.DrawingArea ()
        // conecta el área de dibujo al método dibujar
        area.draw.connect (dibujar) 
        // añade el área de dibujo a la ventana
        add (area)

    def dibujar (context : Context) : bool      

        context.set_source_rgba (1, 0, 0, 1)        
        context.set_line_width (2)

        context.move_to (200, 100)
        context.line_to (200, 300)

        context.move_to (100, 200)
        context.line_to (300, 200)      

        context.stroke ()

        return true

在此处输入图片说明

更多关于 Genie + Gtk + Cairo 的例子在http://genie.webierta.skn1.com

可能有人请告诉我用C语言开罗Gtk3绘制的一条线的最小工作例子GtkDrawingArea 我试图修改testcairo.c测试文件夹中的testcairo.c,但无法正常工作。 请不要在开罗网站上建议教程; Zetcode.com或gnome.org要么不与Gtk3一起使用,要么不是最少的工作示例。

可能有人请告诉我用C语言开罗Gtk3绘制的一条线的最小工作例子GtkDrawingArea 我试图修改testcairo.c测试文件夹中的testcairo.c,但无法正常工作。 请不要在开罗网站上建议教程; Zetcode.com或gnome.org要么不与Gtk3一起使用,要么不是最少的工作示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM