【问题标题】:gtkmm3 drawings outside on_drawgtkmm3 图纸在 on_draw 之外
【发布时间】:2019-12-18 06:29:42
【问题描述】:

我正在开发实时绘图应用程序,其中将在屏幕上绘制数据流。之前使用 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 派生类,然后尝试使用Gtk::Bin,同时添加begin_paint_rect 调用。

除了on_draw以外的地方禁止画画吗?

【问题讨论】:

    标签: cairo gtkmm3


    【解决方案1】:

    对于像情节这样的东西(或任何绘制起来相当复杂的东西),我建议使用缓冲区;我失去了一个月的生命,因为我读到 gtkmm3 确实进行了缓冲,因此不再需要使用“双缓冲”(与 gtkmm2 不同),但它并不是那么简单(阅读:这不是真的)。​​

    所以,你应该做的只是画到你自己的表面;并且每次您更改某些内容时,请致电 queue_draw_regionqueue_draw_area

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

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

    【讨论】:

    • 感谢您的确认。是的..这最终也是我来实施的。但是我正在使用内存有限的嵌入式平台,所以我不保留屏幕缓冲区(如 Cairo::ImageSurface)。相反,我将原始波形数据存储在缓冲区中。每次我获得新的数据点时,我都会排队一个区域(列)以重新绘制,该区域是根据新的数据点集计算的。然后在 on_draw 函数中,我根据剪辑矩形计算索引,然后将它们绘制出来。确实它比我希望的要复杂得多,但它运行良好。
    • 我同意,必须弄清楚要从矩形列表中绘制哪些元素(而不是仅仅从缓冲区复制)是一件很痛苦的事情;但这也是我现在所做的,即使是我的棋盘小部件;)。电路板周围也存在八个不同部分的边缘,所以我找到哪些部分与给定的矩形重叠,然后绘制它们(这样当两个不同的矩形重叠同一个元素时,我不会绘制该元素两次!) .
    【解决方案2】:

    是否禁止在on_draw以外的地方画画?

    基本上:是的。

    这个想法是当你想引起重绘时你调用gtk_widget_queue_draw()gtk_widget_queue_draw_area()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-15
      相关资源
      最近更新 更多