GTK3 和 cairo 太慢了
GTK3 and cairo too slow
我用 GTK3 和 cairo 制作了一个非常简单的动画,但对于这个简单的图形来说速度太慢了。我不明白为什么这么慢。我尝试使用 gtk_widget_queue_draw_area,但结果是一样的,没有任何变化。
谁能解释一下,为什么这么慢,我该如何解决?
程序如下:
#include <gtk/gtk.h>
#include <cairo.h>
void draw(GtkWidget* widget, cairo_t* cr)
{
static int width, height,
posX = 0,
vX = 1;
GtkWidget* window = gtk_widget_get_toplevel(widget);
gtk_window_get_size(GTK_WINDOW(window), &width, &height);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 1);
cairo_rectangle(cr, posX, height/2, 1, 1);
cairo_stroke(cr);
if(posX + vX >= width || posX + vX == 0)
vX = -vX;
posX += vX;
gtk_widget_queue_draw(window);
}
int main(int argc, char** argv)
{
GtkWidget* window;
GtkWidget* darea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(draw), NULL);
gtk_widget_show_all(window);
gtk_main();
}
你应该使用定时器,例如g_timeout_add。您可以使用 g_timeout_add
注册您的新函数 redraw
每 0.05 秒调用一次(例如,每 50 毫秒),并且 redraw
不仅应该绘制东西而且 return TRUE
50 毫秒后重新启动。你会发现这样的 50 毫秒延迟可能太小了,你肯定想增加它。
(请注意,您的程序只需要 CPU 时间的 3%,在 Intel i5-4690S 上用 time(1)... 在 Linux/Debian/Sid/x86-64 上测量,所以它不是太慢;计算机花费 97% 的时间等待!还请记住,人眼在大多数情况下不会比 30 到 60 Hz 快很多)
你的程序中没有动画代码(因为任何动画都应该周期性运行)。 event loop(在gtk_main
中)仅在需要时调用。您可能只想部分地重新粉刷 window。
你的做法是错误的。您不想用 gtk_widget_queue_draw
重复绘图,您希望它定期再次发生(例如,从 g_timeout_add
注册的新 redraw
例程中调用 gtk_widget_queue_draw
。您将通过实验调整该周期。
您也可以使用 gtk_widget_add_tick_callback(如 c-smile 所评论)。我认为您不需要它(因为我猜您的动画可能 运行 太快了)。
研究一些GTK examples (notably the clock example). See also and that. Look into the custom drawing example, and into the source of aclock的源代码。
(你的程序不是太慢,但你的draw
可能被调用不够频繁;没有代码重复它;你应该use the gdb
debugger并编译你的-Wall -g
的代码传递给 gcc
- 除了 pkg-config
)
提供的其他标志
我用 GTK3 和 cairo 制作了一个非常简单的动画,但对于这个简单的图形来说速度太慢了。我不明白为什么这么慢。我尝试使用 gtk_widget_queue_draw_area,但结果是一样的,没有任何变化。 谁能解释一下,为什么这么慢,我该如何解决?
程序如下:
#include <gtk/gtk.h>
#include <cairo.h>
void draw(GtkWidget* widget, cairo_t* cr)
{
static int width, height,
posX = 0,
vX = 1;
GtkWidget* window = gtk_widget_get_toplevel(widget);
gtk_window_get_size(GTK_WINDOW(window), &width, &height);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 1);
cairo_rectangle(cr, posX, height/2, 1, 1);
cairo_stroke(cr);
if(posX + vX >= width || posX + vX == 0)
vX = -vX;
posX += vX;
gtk_widget_queue_draw(window);
}
int main(int argc, char** argv)
{
GtkWidget* window;
GtkWidget* darea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(draw), NULL);
gtk_widget_show_all(window);
gtk_main();
}
你应该使用定时器,例如g_timeout_add。您可以使用 g_timeout_add
注册您的新函数 redraw
每 0.05 秒调用一次(例如,每 50 毫秒),并且 redraw
不仅应该绘制东西而且 return TRUE
50 毫秒后重新启动。你会发现这样的 50 毫秒延迟可能太小了,你肯定想增加它。
(请注意,您的程序只需要 CPU 时间的 3%,在 Intel i5-4690S 上用 time(1)... 在 Linux/Debian/Sid/x86-64 上测量,所以它不是太慢;计算机花费 97% 的时间等待!还请记住,人眼在大多数情况下不会比 30 到 60 Hz 快很多)
你的程序中没有动画代码(因为任何动画都应该周期性运行)。 event loop(在gtk_main
中)仅在需要时调用。您可能只想部分地重新粉刷 window。
你的做法是错误的。您不想用 gtk_widget_queue_draw
重复绘图,您希望它定期再次发生(例如,从 g_timeout_add
注册的新 redraw
例程中调用 gtk_widget_queue_draw
。您将通过实验调整该周期。
您也可以使用 gtk_widget_add_tick_callback(如 c-smile 所评论)。我认为您不需要它(因为我猜您的动画可能 运行 太快了)。
研究一些GTK examples (notably the clock example). See also
(你的程序不是太慢,但你的draw
可能被调用不够频繁;没有代码重复它;你应该use the gdb
debugger并编译你的-Wall -g
的代码传递给 gcc
- 除了 pkg-config
)