1

我可以将画家放入类变量中吗?:

protected:
QPainter *myPainter;

...

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

3 回答 3

3

一种新的分析器,可以更具体地解决更多的重入问题......

danatel对此消息发表了以下评论(部分):

重入是指这种特定情况:1)paintEvent 处理程序将 QPainter 保存到类变量中。2)paintEvent 处理程序调用子程序来绘制东西 3)其中一个子程序调用 Qt 方法 4)这个 Qt 方法递归地生成另一个paintEvent

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

例如,让我们按照您的步骤并更详细地检查它们。

  1. Foo::paintEvent()handler 创建一个 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。

上面的顺序很好,因为 update 创建了一个 event,这意味着延迟处理。相反,如果您调用 Foo::repaint(),这将导致立即递归到 Foo::paintEvent(),这将导致 Qt 中止,因为您正在为同一个对象创建超过 1 个画家,或者您的程序中止因为它最终(你知道,在几百毫秒内)炸毁了堆栈。

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

于 2008-10-24T01:10:57.617 回答
2

不要那样做。只需将它放在堆栈上,这样当它在析构函数中被销毁时,它就会自动执行绘画。

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    // use painter
    ...
    // paint object automatically closes and paint on desctruction
}
于 2008-10-11T04:45:03.073 回答
1

如果您试图避免将painter 小部件传递给许多子例程调用,您可能可以将指向painter 的指针作为类变量来逃避。如前所述,您仍然应该在paintEvent 函数中创建/销毁它。就个人而言,我可能只是将它传递给辅助函数,但你可以这样做。

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

于 2008-10-12T17:37:51.217 回答