我在Ubuntu 12.04 LTS 32位上使用带有gtkmm3的GNU工具链的C ++ 11。 我一直在玩Programming with gtkmm 3中的gtkmm3的一些例子。
基于17.2.1.Example,我继承自Gtk::DrawingArea
(MyDrawingArea
此处)并覆盖on_draw()
事件处理程序,如下所示:
MyDrawingArea.hpp
...
protected:
bool on_draw ( const Cairo::RefPtr<Cairo::Context>& cr ) override;
MyDrawingArea.cpp
bool MyDrawingArea::on_draw( const Cairo::RefPtr<Cairo::Context>& cr )
{
Gtk::Allocation allocation = get_allocation( );
const int width = allocation.get_width( );
const int height = allocation.get_height( );
int coord1{ height - 3 };
cr->set_line_width( 3.0 );
this->get_window( )->freeze_updates( );
cr->set_source_rgb( 0, 0.40, 0.60 );
cr->move_to( 0, coord1 );
cr->line_to( width, coord1 );
cr->stroke( );
cr->set_source_rgb( 1, 0.05, 1 );
cr->move_to( mXStart, coord1 );
cr->line_to( mXStart, mYAxis * 1.5 );
cr->show_text( to_string( mYAxis ) );
cr->stroke( );
mXStart += 5;
this->get_window( )->thaw_updates( );
return true;
}
我的目标是根据我在一个小测试应用程序中进行的计算绘制一个简单的条形图,这个想法是每次调用on_draw()
事件时,下一个条形将被移动5个单位到在mXAxis
右侧,将根据新的mYaxis
值绘制一条垂直线,该值是根据新计算的结果计算的。
当我想重新绘制我的图形并触发MyDrawingArea :: on_draw()事件时,我在计算完成后从我的应用程序调用MyDrawingArea.show_all(),并设置了新的x和y轴。
但是,这并不像我预期的那样有效:MyDrawingArea.show_all()
使整个绘图窗口无效并从头开始绘制:新图形线显示在正确的位置,但之前的是擦除。我也试过MyDrawingArea.queue_draw()
,效果相同。 但我想保留以前的图表结果,以便我可以获得计算结果的配置文件,因为我使用不同的值进行计算。
此实现还会导致我的图表(我的图表上的x轴)的底线 - 由我的代码示例中的第一个stroke()
调用绘制,在每次调用on_draw()时重新呈现 - 虽然这不应该是必需的,因为这一行在MyDrawingArea
的生命周期内持续存在 - 不应该像我的代码当前所做的那样,在每个新的on_draw()
事件上使其无效并重新绘制它,因为我还没有办法解决这个问题。
我对开罗很新,所以我确信我可能完全错了,但明确的,面向任务的文档看起来很少 - 没有找到任何解释如何做到这一点,尽管我我相信它很简单。
我需要做什么才能在Gtk::DrawingArea
上绘制一个新行,同时保留先前已经在之前的过程中绘制的前一个图形线,并建立将在生命周期中保留的图形元素。 Gtk::DrawingArea
小部件。显然,使用show_all()
或queue_draw()
并在on_draw()
事件中完成所有操作都无法实现。
答案 0 :(得分:4)
通常,您必须绘制整个小部件,Cairo会将绘图剪切到预定义的脏区域。有关性能提示,请参阅“GtkWidget :: draw”信号的GTK参考手册:
信号处理程序将获得一个已经设置为剪辑区域的cr 小部件的脏区域,即需要重新绘制的区域。 复杂的小部件,希望避免完全重绘自己 可以获得剪辑区域的完整范围 gdk_cairo_get_clip_rectangle(),或者他们可以获得更细粒度 肮脏地区的代表 cairo_copy_clip_rectangle_list()。
因此,您可以使用gtk_widget_queue_draw_area()仅重绘所需的区域。