[有人可以给我展示一个最小的工作示例,该示例在Ct上将C语言用于Cairo与Gtk3在GtkDrawingArea
中绘制一行。我试图修改Gtk3测试文件夹中的testcairo.c
,但无法使其正常工作。请不要在开罗网站上建议教程; Zetcode.com或gnome.org要么不与Gtk3一起使用,要么不是最小的工作示例。
我明白了。关键区别在于,对于gtk + 3,您必须从“绘制”信号处理程序中进行绘制。使用gtk + 2,它来自“ expose-event”信号处理程序。这是一个最小的工作示例:http://www.gtkforums.com/viewtopic.php?f=3&t=988&p=195286=Drawing+with+Cairo+in+GTK3#p195286
这是一个完整的工作示例:
确保已安装gtk3-devel
(在Fedora #dnf中安装gtk3-devel)
在Ubuntu中:sudo apt install libgtk-3-dev
编译:gcc draw.c
pkg-config --cflags gtk+-3.0 --libs gtk+-3.0
-o draw
pkg-config --cflags gtk+-3.0 --libs gtk+-3.0
我不明白为什么它不起作用,它应该起作用。
#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;
}
您可以看到,带有开罗的gtk2与gtk3几乎相同。
http://developer.gnome.org/gtk3/3.2/GtkDrawingArea.html
// 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
是-我同意...看起来应该对我有用。
但是我有一个单独的问题...我试图使用旋转框来控制要绘制多少条“线”(或图案..)。
我已经将信号连接到DrawingArea进行“绘制”,但是当旋转改变时,我不知道如何重新调用“绘制”回调函数?
任何想法?
自己解决了!
需要使用gtk_widget_queue_draw_area()函数。
main.c:
http://genie.webierta.skn1.com
Glade文件
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gtk/gtk.h>
#include <cairo.h>
GtkWidget *window1;
GtkWidget *fixed1;
GtkWidget *frame1;
GtkWidget *draw1;
GtkWidget *spin1;
GtkWidget *spin2;
GtkBuilder *builder1;
// Neural Network Setup
gint N = 2; // number of layers (hard-coded for now)
gint n1; // number of neurons in first layer
gint n2; // number of neurons in second layer
gint L; // index for tracking each neuron layer
// Graphics Plotting Setup
gdouble W = 500.0; // hard-coded for now
gdouble H = 300.0; // hard-coded for now
gdouble mx = 20.0; // fixed x-margin
gdouble my = 20.0; // fixed y-margin
gdouble X; // total "plotting" width
gdouble Y; // total "plotting" height
gdouble dx; // equal x-spacing between neurons
gdouble dy; // equal y-spacing between neurons
gdouble x;
gdouble y;
gdouble r = 20.0; // radius
/*
- redraw (on event..?)
*/
static gboolean on_draw1_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
cairo_set_line_width(cr, 1);
int i = 0;
// draw first layer neutrons
L = 0;
dy = Y / (n1 + 1);
x = mx + ((L + 1) * dx); // x-coordinate of given neuron
for (i = 0; i < n1; i++)
{
y = my + ((i + 1) * dy); // y-coordinate of given neuron
cairo_move_to(cr, x + r, y);
cairo_arc(cr, x, y, r, 0.0, 2.0 * M_PI);
cairo_close_path(cr);
}
// draw second layer neutrons
L = 1;
dy = Y / (n2 + 1);
x = mx + ((L + 1) * dx);
for (i = 0; i < n2; i++)
{
y = my + ((i + 1) * dy);
cairo_move_to(cr, x + r, y);
cairo_arc(cr, x, y, r, 0.0, 2.0 * M_PI);
cairo_close_path(cr);
}
cairo_stroke(cr);
//cairo_fill(cr);
// FALSE -> allow further events
return FALSE;
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
builder1 = gtk_builder_new_from_file("main2.ui");
window1 = GTK_WIDGET(gtk_builder_get_object(builder1, "window1"));
fixed1 = GTK_WIDGET(gtk_builder_get_object(builder1, "fixed1"));
draw1 = GTK_WIDGET(gtk_builder_get_object(builder1, "draw1"));
spin1 = GTK_WIDGET(gtk_builder_get_object(builder1, "spin1"));
spin2 = GTK_WIDGET(gtk_builder_get_object(builder1, "spin2"));
g_signal_connect(window1, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(draw1), "draw", G_CALLBACK(on_draw1_draw), NULL);
gtk_widget_add_events(draw1, 0);
gtk_builder_connect_signals(builder1, NULL);
g_object_unref(builder1);
n1 = 3;
n2 = 2;
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin1), (gdouble)n1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin2), (gdouble)n2);
X = W - (2 * mx);
Y = H - (2 * my);
dx = X / (N + 1);
gtk_widget_show_all(window1);
gtk_main();
return 0;
}
void on_spin1_value_changed(GtkSpinButton *b)
{
n1 = gtk_spin_button_get_value_as_int(b);
}
void on_spin2_value_changed(GtkSpinButton *b)
{
n2 = gtk_spin_button_get_value_as_int(b);
}