外面的 gtkmm3 图纸 on_draw
gtkmm3 drawings outside on_draw
我正在开发实时绘图应用程序,其中将在屏幕上绘制数据流。早些时候使用 gtkmm2 我使用自定义小部件(派生自 Gtk::Bin
)完成了此操作,其中我有一个创建 cairo 上下文并进行绘图的成员函数。
现在使用 gtkmm3 除了 on_draw
,我无法用任何方法绘图。这是我的自定义绘制方法主体的样子
Gtk::Allocation oAllocation = get_allocation();
Glib::RefPtr <Gdk::Window> refWindow = get_window();
Cairo::RefPtr <Cairo::Context> refContext =
refWindow->create_cairo_context();
refWindow->begin_paint_rect(oAllocation); //added later
refContext->save();
refContext->reset_clip();
refContext->set_source_rgba(1,
1,
1,
1);
refContext->move_to(oAllocation.get_x(),
oAllocation.get_y());
refContext->line_to(oAllocation.get_x()
+ oAllocation.get_width(),
oAllocation.get_y()
+ oAllocation.get_height());
refContext->stroke();
refContext->restore();
refWindow->end_paint();
最初我从 Gtk::DrawingArea
派生了 class,然后在添加 begin_paint_rect
调用时尝试使用 Gtk::Bin
。
是否禁止在on_draw
以外的地方画画?
Is it forbidden to draw in any place other than on_draw?
基本上:是的。
这个想法是当你想引起重绘时调用 gtk_widget_queue_draw()
或 gtk_widget_queue_draw_area()
。
对于绘图之类的东西(或任何绘制起来相当复杂的东西),我建议使用缓冲区;我失去了一个月的生命,因为我读到 gtkmm3 确实进行了缓冲,因此不再需要使用“双缓冲”(与 gtkmm2 相反),但这并不那么简单(阅读:那不是真的)。
所以,你应该做的只是画出你自己的表面;每次你改变一些东西时调用 queue_draw_region
或 queue_draw_area
.
然后在 on_draw
中获取剪辑矩形列表,并将它们从您的私有表面复制到传递给 on_draw
函数的 cr
。开罗通常会
完全相同的东西(或者他们声称如此),将您刚刚复制的内容再次复制到屏幕上;所以你应该把它关掉(我读到这应该是可能的)。
你不能使用 Cairo 缓冲的原因是因为它不保留该缓冲区;你得到的是一些损坏的表面,所以你被迫重绘剪辑矩形列表中的所有内容。如果您(您的应用程序)是唯一进行更改的人(根据您的 queue_draw_* 调用),那不会太糟糕:然后您可以设置一个标志,使需要重绘的部分无效,然后简单地将抽奖推迟到 on_draw
。但有时 on_draw
会因其他原因而被调用,例如,当您打开一个覆盖绘图区域的菜单时。我认为这是一个错误(或设计错误),但事实就是如此。结果是除了查看剪辑矩形列表之外,您不知道必须重绘什么;这使得仅绘制区域的一部分变得异常困难,除非您的绘图由许多单独的矩形组成(例如,棋盘)。唯一可行的方法是在内存(您的私人表面)中保留图像的完整副本,然后在 on_draw
.
中从那里复制剪辑矩形列表
我正在开发实时绘图应用程序,其中将在屏幕上绘制数据流。早些时候使用 gtkmm2 我使用自定义小部件(派生自 Gtk::Bin
)完成了此操作,其中我有一个创建 cairo 上下文并进行绘图的成员函数。
现在使用 gtkmm3 除了 on_draw
,我无法用任何方法绘图。这是我的自定义绘制方法主体的样子
Gtk::Allocation oAllocation = get_allocation();
Glib::RefPtr <Gdk::Window> refWindow = get_window();
Cairo::RefPtr <Cairo::Context> refContext =
refWindow->create_cairo_context();
refWindow->begin_paint_rect(oAllocation); //added later
refContext->save();
refContext->reset_clip();
refContext->set_source_rgba(1,
1,
1,
1);
refContext->move_to(oAllocation.get_x(),
oAllocation.get_y());
refContext->line_to(oAllocation.get_x()
+ oAllocation.get_width(),
oAllocation.get_y()
+ oAllocation.get_height());
refContext->stroke();
refContext->restore();
refWindow->end_paint();
最初我从 Gtk::DrawingArea
派生了 class,然后在添加 begin_paint_rect
调用时尝试使用 Gtk::Bin
。
是否禁止在on_draw
以外的地方画画?
Is it forbidden to draw in any place other than on_draw?
基本上:是的。
这个想法是当你想引起重绘时调用 gtk_widget_queue_draw()
或 gtk_widget_queue_draw_area()
。
对于绘图之类的东西(或任何绘制起来相当复杂的东西),我建议使用缓冲区;我失去了一个月的生命,因为我读到 gtkmm3 确实进行了缓冲,因此不再需要使用“双缓冲”(与 gtkmm2 相反),但这并不那么简单(阅读:那不是真的)。
所以,你应该做的只是画出你自己的表面;每次你改变一些东西时调用 queue_draw_region
或 queue_draw_area
.
然后在 on_draw
中获取剪辑矩形列表,并将它们从您的私有表面复制到传递给 on_draw
函数的 cr
。开罗通常会
完全相同的东西(或者他们声称如此),将您刚刚复制的内容再次复制到屏幕上;所以你应该把它关掉(我读到这应该是可能的)。
你不能使用 Cairo 缓冲的原因是因为它不保留该缓冲区;你得到的是一些损坏的表面,所以你被迫重绘剪辑矩形列表中的所有内容。如果您(您的应用程序)是唯一进行更改的人(根据您的 queue_draw_* 调用),那不会太糟糕:然后您可以设置一个标志,使需要重绘的部分无效,然后简单地将抽奖推迟到 on_draw
。但有时 on_draw
会因其他原因而被调用,例如,当您打开一个覆盖绘图区域的菜单时。我认为这是一个错误(或设计错误),但事实就是如此。结果是除了查看剪辑矩形列表之外,您不知道必须重绘什么;这使得仅绘制区域的一部分变得异常困难,除非您的绘图由许多单独的矩形组成(例如,棋盘)。唯一可行的方法是在内存(您的私人表面)中保留图像的完整副本,然后在 on_draw
.