外面的 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_regionqueue_draw_area.

然后在 on_draw 中获取剪辑矩形列表,并将它们从您的私有表面复制到传递给 on_draw 函数的 cr。开罗通常会 完全相同的东西(或者他们声称如此),将您刚刚复制的内容再次复制到屏幕上;所以你应该把它关掉(我读到这应该是可能的)。

你不能使用 Cairo 缓冲的原因是因为它不保留该缓冲区;你得到的是一些损坏的表面,所以你被迫重绘剪辑矩形列表中的所有内容。如果您(您的应用程序)是唯一进行更改的人(根据您的 queue_draw_* 调用),那不会太糟糕:然后您可以设置一个标志,使需要重绘的部分无效,然后简单地将抽奖推迟到 on_draw。但有时 on_draw 会因其他原因而被调用,例如,当您打开一个覆盖绘图区域的菜单时。我认为这是一个错误(或设计错误),但事实就是如此。结果是除了查看剪辑矩形列表之外,您不知道必须重绘什么;这使得仅绘制区域的一部分变得异常困难,除非您的绘图由许多单独的矩形组成(例如,棋盘)。唯一可行的方法是在内存(您的私人表面)中保留图像的完整副本,然后在 on_draw.

中从那里复制剪辑矩形列表