I am using C++11 with GNU tool chain with gtkmm3, on Ubuntu 12.04 LTS 32 bit. I have been playing wtih some of the examples for gtkmm3 in Programming with gtkmm 3.
Based on 17.2.1.Example there, I inherited from Gtk::DrawingArea
(MyDrawingArea
here) and overrode the on_draw()
event handler as follows:
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;
}
My goal is to draw a simple bar graph based on a calculation I do in a little test application, the idea being that each time the on_draw()
event is called, the next bar would be moved 5 units to the right on mXAxis
and a vertical line would be drawn based on the new mYaxis
value, which is computed based on the results of the new calculation.
When I want to repaint my graph and trigger the MyDrawingArea::on_draw() event, I call MyDrawingArea.show_all() from my application after the calculation has completed, and new x and y axes have been set.
However, this does not work as I expected: MyDrawingArea.show_all()
invalidates the entire drawing window and draws from scratch: the new graph line appears in its proper place, but the previous ones are erased. I also tried MyDrawingArea.queue_draw()
, which had the same effect. But I want to persist the previous graph results so I can get a profile of the calculation results, as I calculate with different values.
This implementation is also causing the bottom line on my graph (my x axis on the graph)- drawn by the first stroke()
call in my code example, to be rendered anew on each call to on_draw() - although this should not be necassary since this line persists for the lifetime of MyDrawingArea
- it should not be necessary to invalidate and then re-draw it on each new on_draw()
event, as my code is currently doing, because I am haven't yet found a way to handle this.
I am very new to Cairo, so I'm sure I'm probably doing this completely wrong, but explicit, task-oriented documentation appears to be sparse - have not found anything that explains how to do this, although I'm sure it is quite simple.
What do I need to do to draw a new line on Gtk::DrawingArea
, while persisting previous graph lines that have already been drawn on previous passes, and establish graphics elements that will persist for the lifetime of the Gtk::DrawingArea
widget. Obviously using show_all()
or queue_draw()
and doing it all in the on_draw()
event is not the way to go.