开罗和 GTK+,未知的绘制事件调用和程序停止
Cairo and GTK+, unknown draw event call and program stop
我正在使用 Cairo 和 GTK3.0,我遇到了不知道如何解决的问题。
目前我有 2 个奇怪的问题,我不知道如何解决。
- 每当终端漂浮在绘图上时调用绘制事件 window。
- 程序没有通过gtk_main();功能。
我将在下面提供我的代码,这是非常基础的,它基于此:http://zetcode.com/gfx/cairo/cairobackends/,GTK window 部分。
我最终只需要一个 window,我可以在我的代码中随时调用绘制事件。
#include <cairo.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int xStart;
int yStart;
int xEnd;
int yEnd;
} lineData;
int i = 0;
int gonnaDraw = 0;
lineData *lines;
int lineSize = 0;
/**
* The drawing with the cairo elements is done here.
* The new line is saved to an array.
* Eventually there should be a loop that draws all lines in the array.
*/
static void do_drawing(cairo_t *cr) {
printf("I'm endless, somehow.\n");
if(lineSize != 0) { //We only want to draw in the infinite for loop, not before it.
cairo_set_source_rgb(cr, 255, 0, 0);
cairo_set_line_width(cr, 1.0);
lineData newLine = { 10.0 + i, 50.0 + i, 100.0 + i, 50.0 + i };
//lines[lineSize - 1] = newLine;
cairo_move_to(cr, newLine.xStart, newLine.xEnd);
cairo_line_to(cr, newLine.yStart, newLine.yEnd);
cairo_stroke(cr);
i = i + 10;
printf("i: %d\n", i);
gonnaDraw = 1;
}
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) {
do_drawing(cr);
return FALSE;
}
int main (int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *darea;
printf("1\n");
gtk_init(&argc, &argv);
printf("2\n");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
printf("3\n");
darea = gtk_drawing_area_new();
printf("4\n");
gtk_container_add(GTK_CONTAINER(window), darea);
printf("5\n");
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
printf("6\n");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 800);
gtk_window_set_title(GTK_WINDOW(window), "GTK window");
printf("7\n");
gtk_widget_show_all(window);
printf("8\n");
gtk_main(); // If I'm removed I got no drawing window.
printf("9\n"); // I do not show up.
lines = (lineData *) malloc(lineSize * sizeof(lineData));
for(;;) {
if(gonnaDraw == 1) {
lineSize++;
printf("lineSize: %d\n", lineSize);
lines = (lineData *) realloc(lines, lineSize * sizeof(lineData));
gtk_widget_queue_draw(window);
gonnaDraw = 0;
}
}
return 0;
}
使用标准方法编译。
GTK+的绘图模型你已经基本了解了。问题 1 是它的结果:当另一个 window 越过你的区域时,window 系统告诉 GTK+ 该区域需要重新绘制。这就是我说的剪裁的意思。
现在另一部分是了解 GTK+ 事件模型。所有 window 系统都以这样的方式运行,即所有程序 运行 在一个由 组成的循环中,当程序处于活动状态时,从 window 系统获取消息并采取行动在上面。这就是 gtk_main()
所做的。 gtk_main()
不return正常;它不会 return 直到调用 gtk_main_quit()
。除了在与小部件交互时使用信号来执行操作外,您还可以通过两种方式“挂钩”主循环:g_timeout_add()
,其中 运行 是一个按计划运行的函数,g_idle_add()
,这 运行 是下一个可能的函数。如果您希望某事经常发生,前者很有用;如果您希望工作线程向 UI 发出更新信号,则后者很有用。有关主循环的 GLib 文档会告诉您更多信息。我仍然不确定您的最终目标是什么,所以我想您可以尝试同时玩这两种游戏,看看会发生什么。
– 和实验室
我正在使用 Cairo 和 GTK3.0,我遇到了不知道如何解决的问题。
目前我有 2 个奇怪的问题,我不知道如何解决。
- 每当终端漂浮在绘图上时调用绘制事件 window。
- 程序没有通过gtk_main();功能。
我将在下面提供我的代码,这是非常基础的,它基于此:http://zetcode.com/gfx/cairo/cairobackends/,GTK window 部分。 我最终只需要一个 window,我可以在我的代码中随时调用绘制事件。
#include <cairo.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int xStart;
int yStart;
int xEnd;
int yEnd;
} lineData;
int i = 0;
int gonnaDraw = 0;
lineData *lines;
int lineSize = 0;
/**
* The drawing with the cairo elements is done here.
* The new line is saved to an array.
* Eventually there should be a loop that draws all lines in the array.
*/
static void do_drawing(cairo_t *cr) {
printf("I'm endless, somehow.\n");
if(lineSize != 0) { //We only want to draw in the infinite for loop, not before it.
cairo_set_source_rgb(cr, 255, 0, 0);
cairo_set_line_width(cr, 1.0);
lineData newLine = { 10.0 + i, 50.0 + i, 100.0 + i, 50.0 + i };
//lines[lineSize - 1] = newLine;
cairo_move_to(cr, newLine.xStart, newLine.xEnd);
cairo_line_to(cr, newLine.yStart, newLine.yEnd);
cairo_stroke(cr);
i = i + 10;
printf("i: %d\n", i);
gonnaDraw = 1;
}
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) {
do_drawing(cr);
return FALSE;
}
int main (int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *darea;
printf("1\n");
gtk_init(&argc, &argv);
printf("2\n");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
printf("3\n");
darea = gtk_drawing_area_new();
printf("4\n");
gtk_container_add(GTK_CONTAINER(window), darea);
printf("5\n");
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
printf("6\n");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 800);
gtk_window_set_title(GTK_WINDOW(window), "GTK window");
printf("7\n");
gtk_widget_show_all(window);
printf("8\n");
gtk_main(); // If I'm removed I got no drawing window.
printf("9\n"); // I do not show up.
lines = (lineData *) malloc(lineSize * sizeof(lineData));
for(;;) {
if(gonnaDraw == 1) {
lineSize++;
printf("lineSize: %d\n", lineSize);
lines = (lineData *) realloc(lines, lineSize * sizeof(lineData));
gtk_widget_queue_draw(window);
gonnaDraw = 0;
}
}
return 0;
}
使用标准方法编译。
GTK+的绘图模型你已经基本了解了。问题 1 是它的结果:当另一个 window 越过你的区域时,window 系统告诉 GTK+ 该区域需要重新绘制。这就是我说的剪裁的意思。
现在另一部分是了解 GTK+ 事件模型。所有 window 系统都以这样的方式运行,即所有程序 运行 在一个由 组成的循环中,当程序处于活动状态时,从 window 系统获取消息并采取行动在上面。这就是 gtk_main()
所做的。 gtk_main()
不return正常;它不会 return 直到调用 gtk_main_quit()
。除了在与小部件交互时使用信号来执行操作外,您还可以通过两种方式“挂钩”主循环:g_timeout_add()
,其中 运行 是一个按计划运行的函数,g_idle_add()
,这 运行 是下一个可能的函数。如果您希望某事经常发生,前者很有用;如果您希望工作线程向 UI 发出更新信号,则后者很有用。有关主循环的 GLib 文档会告诉您更多信息。我仍然不确定您的最终目标是什么,所以我想您可以尝试同时玩这两种游戏,看看会发生什么。
– 和实验室