tags:

views:

894

answers:

3

Can I put the painter into the class variables? :

protected:
QPainter *myPainter;

...

void MyWidget::paintEvent(QPaintEvent *event)
{
    myPainter = new QPainter(this);
+2  A: 

don't do that. just put it on the stack so that when it is destroyed in the destructor it will perform the painting automatically.

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    // use painter
    ...
    // paint object automatically closes and paint on desctruction
}
IIRC there is a note in the QT manuals that expressly states to recreate the Painter for every paint event
Harald Scheirich
Please see my comment above.
danatel
"The common use of QPainter is inside a widget's paint event: Construct and customize (e.g. set the pen or the brush) the painter. Then draw. Remember to destroy the QPainter object after drawing."
Max Howell
Thank you for your answer.
danatel
+1  A: 

If you are trying to avoid passing the painter widget to a number of subroutine calls, you can probably get away with a pointer to the painter as a class variable. As mentioned, you should still create/destroy it in the paintEvent function. Personally, I would probably just pass it to the helper functions, but you could do it this way.

Also, I'm not sure how your question related to reentrancy. All of the painting of UI elements should only be in the UI thread, if you have multiple threads. You can do a painter on an image in a different thread, but in that case you'd probably want to only be painting that image in that thread, not in multiple threads. Either way, I don't think you'd run into problems with reentrancy in the Qt functions you would call on a painter as long as you kept to those conditions.

Caleb Huitt - cjhuitt
Thank you for your answer. By reentrancy I mean this specific situation:1) paintEvent handler saves a QPainter to a class variable.2) paintEvent handler calls subroutines to draw something3) one of the subroutines calls a Qt method 4) this Qt method generates another paintEvent recursively
danatel
+2  A: 

A new anser to address more reentrancy more specifically...

danatel left the following comment to this message (in part):

By reentrancy I mean this specific situation: 1) paintEvent handler saves a QPainter to a class variable. 2) paintEvent handler calls subroutines to draw something 3) one of the subroutines calls a Qt method 4) this Qt method generates another paintEvent recursively

The answer to this is that it should likely be acceptable, unless you do something really odd. (And if you do something that odd, Qt will likely warn you or abort.) I think there might still be some confusion over what you mean by reentrant, but generating a paintEvent won't stop the execution flow of the current action to immediately process that event. Instead (like all events), it will be queued up for later processing. As long as you aren't doing multi-threading or calling processEvents, the execution order of the code while you are in one of your own functions should be very straightforward.

As an example, let's follow your steps and examine them in more detail.

  1. Foo::paintEvent() handler creates a QPainter and sets Foo::m_painter_p at it.
  2. Foo::paintEvent() calls Foo::paintAntarticaFlag().
  3. Foo::paintAntarticaFlag(): a) uses Foo::m_painter_p, then b) calls something that calls Foo::update(), then c) uses Foo::m_painter_p some more.
  4. Foo::update(), which is really a Qt method, generates a paintEvent for Foo.

The above sequence is fine, since update creates an event, which means delayed processing. If instead you called Foo::repaint(), that would cause an immediate recursion into Foo::paintEvent(), which would either cause Qt to abort because you are creating more than 1 painter for the same object, or your program to abort because it eventually (you know, in a few hundred milliseconds) blew out the stack.

If you are doing multiple threads and just want to trigger a redraw, you can still do that from the other thread, since it will just put a paintEvent on the queue to be handled by the proper thread at the proper time. If you are doing multiple threads and want to draw those flags using the same painter, well, don't. Just don't. In that case, you might consider drawing each flag to a shared image, and drawing that image where you are using the QPainter now.

Caleb Huitt - cjhuitt