2008-10-11 85 views
1

我可以让画家进入类变量吗? :Qt :: paintEvent是否需要重入?

protected: 
QPainter *myPainter; 

... 

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

你为什么要这么做?为什么不把它放在堆栈上? – shoosh 2008-10-11 06:16:50

+0

应用程序绘制航海标志。我想创建十几种绘制标记元素的方法,并将它们组合到paintEvent中。我想要的方法像“DrawWedge()”而不是“DrawWedge(QPainter * painter)”。 – danatel 2008-10-11 19:43:58

回答

3

新雁来解决更重入更具体...

danatel留下这样的评论,以this message(部分):

通过重新进入我的意思是具体情况:1)的paintEvent处理程序将QPainter保存到类变量中。 2)的paintEvent处理程序调用子程序画点什么3)子程序调用之一Qt的方法4)该Qt的方法生成另一个的paintEvent递归

这个问题的答案是,它应该有可能是可以接受的,除非你做的东西真奇怪。 (如果你做了一些奇怪的事情,Qt可能会警告你或中止。)我认为你可能仍然会对可重入的含义产生一些困惑,但是生成paintEvent并不会立即停止当前动作的执行流程处理该事件。相反(像所有事件一样),它将排队等待以后处理。只要你没有进行多线程或调用processEvents,当你在自己的函数中时,代码的执行顺序应该是非常简单的。

作为一个例子,让我们按照您的步骤,并更详细地检查它们。

  1. Foo::paintEvent()处理 创建的QPainter,并设置 Foo::m_painter_p它。
  2. Foo::paintEvent()来电 Foo::paintAntarticaFlag()
  3. Foo::paintAntarticaFlag():a)使用Foo::m_painter_p,然后b)调用一些调用Foo::update()的东西,然后c)使用Foo::m_painter_p多一些。
  4. Foo::update(),这是一个真正的Qt方法,为Foo生成一个paintEvent。

上述顺序很好,因为更新会创建事件,这意味着延迟处理。如果你调用Foo :: repaint(),那会导致立即递归到Foo :: paintEvent()中,这会导致Qt中止,因为你为同一个对象创建了多个画家,或者你的程序要中止因为它最终(你知道,在几百毫秒内)吹掉堆栈。

如果您正在执行多个线程并且只是想触发重绘,您仍然可以从其他线程执行此操作,因为它只会将paintEvent放置在队列中,以便在适当的时候由正确的线程处理。如果你正在做多个线程并且想用同一个画家绘制这些标志,那么不要。不要。在这种情况下,您可以考虑将每个标记绘制到共享图像,然后在现在使用QPainter的位置绘制该图像。

2

不这样做。只需将它放在堆栈上,以便在析构函数中销毁它时,它将自动执行绘画。

void MyWidget::paintEvent(QPaintEvent *event) 
{ 
    QPainter painter(this); 
    // use painter 
    ... 
    // paint object automatically closes and paint on desctruction 
} 
+0

IIRC在QT手册中有一个说明,明确说明为每次绘画事件重新创建画家 – 2008-10-11 10:53:03

1

如果你正试图避免将画家小部件的一些子程序调用的,你也许可以蒙混过关的指针画家为类变量。如前所述,您仍然应该在paintEvent函数中创建/销毁它。就我个人而言,我可能只是将它传递给帮助函数,但你可以这样做。

另外,我不确定你的问题与重入有关。如果您有多个线程,则UI元素的所有绘制应该只在UI线程中。您可以在不同线程中的图像上绘制画家,但在这种情况下,您可能只想在该线程中绘制该图像,而不是在多个线程中绘制该图像。无论哪种方式,只要你遵守这些条件,我认为你不会遇到Qt函数中的重入问题,你可以调用一个画家。