2014-07-02 84 views
2

我在Ubuntu 12.04 LTS 32位上使用带GNU工具链的C++ 11与gtkmm3。 我一直在玩Programming with gtkmm 3的gtkmm3的一些例子。如何在Gtk :: DrawingArea区域绘制一条新线条,同时存在之前已绘制的线条?

基于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()事件中这样做并不是要走的路。

回答

4

通常,您必须绘制整个小部件,Cairo会将图形剪切到预定义的脏区域。还请参阅“的GtkWidget ::抽奖”信号GTK参考手册性能提示:

信号处理程序将获得CR已设置为 widget的脏区域,即需要该地区的剪辑区域重绘。想要完全避免 重绘自己可以得到截取区域的完整程度与 gdk_cairo_get_clip_rectangle(),或者他们可以得到脏区的细粒度 表示与 cairo_copy_clip_rectangle_list 复杂的小部件()。

因此,您可以使用gtk_widget_queue_draw_area()重新绘制所需的区域。

+0

我看到了有关剪辑区域,脏区域等的文档和函数,但无法弄清如何确定脏区域以及如何计算它:由于前一个“绘制”已经完成,因此不是一切都干净下一次呢? (我不仅仅是开罗的新手,我对这类编程一般都是新手 - 我通常会做中间件和服务器端的工作)。无论如何,从你所说的话看来,我有两种选择:坚持我的前一篇每次点和重新绘制所有行;计算我需要为每个通道绘制的脏区域并将绘图限制到该区域? – Vector

+0

脏区域由窗口系统决定,并使用queue_draw *()手动重绘区域。所以是的,要么你重新绘制所有的东西,让剪裁为你解决,或者你计算并排队你的脏区域,并只在脏区域绘制。最有可能的是,您可以重新绘制所有内容,无论如何由于剪辑都足够快。 – elmarco

+2

_最可能的是,您可以重新绘制所有的......_:这就是我选择做的事情 - 对于我来说,将以前绘制的线条存储在容器中并迭代重绘它们比开始弄清楚如何弄脏并跟踪我应该在下一行的位置。这是一个非常简单的应用程序,只是为了教给我自己的基本知识,我不希望陷入这样一种情况,即绘制过程如此延长和复杂,以至于性能会成为一个问题,特别是因为,正如您所解释的那样,击中。 – Vector