2014-07-02 106 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