【问题标题】:QGraphicsItem disappears when calling setPos from a different thread从不同的线程调用 setPos 时 QGraphicsItem 消失
【发布时间】:2015-10-11 15:54:26
【问题描述】:

我在QGraphicsView 上有两种类型的QGraphicsItem­­­­­­s,其中一种在场景中,例如 z-index 为 1 的网格,另一种是蚂蚁,在 z-index 的顶部2. 启动程序时,我将所有蚂蚁设置为位置 0,0 并将它们添加到场景中。但随后我开始通过在它们上调用setPos() 将这些蚂蚁从另一个线程中移出——然后我的电脑吃掉了蚂蚁!他们消失在他们的旧位置,但不会出现在他们的新位置。新位置在场景内。

这是Ant类的代码(继承QGraphicsItem):

#include "ant.h"
#include "constants.h"

#include <QPainter>

Ant::Ant()
{
    setZValue(2);
}

QRectF Ant::boundingRect() const
{
    return QRect(QPoint(0,0), G_FIELD_RECT_SIZE);
}

void Ant::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
    Q_UNUSED(item)
    Q_UNUSED(widget)

    QBrush b = painter->brush();
    if (food())
        painter->setBrush(Qt::blue);
    else
        painter->setBrush(Qt::black);
    painter->drawEllipse(2,3, G_FIELD_RECT_WIDTH - 4, G_FIELD_RECT_HEIGHT - 6);
    painter->setBrush(b);
}

经过更多测试,我发现只要我从 Qt 事件线程中调用 setPos,一切正常。一旦我在自定义线程中调用它,蚂蚁就会消失。知道如何解决这个问题吗?

【问题讨论】:

  • 你应该把 UI 的东西都放在主线程中。 Qt 在这方面存在设计限制。您可以将计算卸载到另一个线程,但所有 GUI 交互都必须在主线程中,
  • @ddriver Ant 类实际上只是用于图形的东西,另一个线程上运行的另一个类正在调用导致问题的setPos 方法

标签: c++ multithreading qt qthread qgraphicsitem


【解决方案1】:

你必须回到主线程执行setPos。正如 ddriver 所评论的,您不应该从线程修改 GUI(这样做时您通常会收到 qDebug 消息,您在调试器窗口中没有收到任何消息吗?)。

你只需要:

  • 向您的Ant 类添加一个新信号(如signalSetPos( QPoint pos )
  • 为您的Ant 类添加一个新槽(如doSetPos( QPoint pos ))。这个插槽实现只是调用setPos(pos)
  • 使用Qt::QueuedConnectionQt::BlockingQueuedConnection 连接它们(connect 函数的第五个参数,对于 GUI 更新,Qt::QueuedConnection 可能更可取,因为它不会阻塞您的线程)。
  • 从你以前执行setPos( newPos ) 的线程中发出signalSetPos( newPos )。然后,doSetPos 将从主线程执行(如果您使用 Qt::QueuedConnection,则稍后,如果您使用 Qt::BlockingQueuedConnection,则立即执行)。

查看这篇文章以获取有关从线程发出信号的更多信息: Qt - emit a signal from a c++ thread

【讨论】:

  • 是的,我确实收到了调试消息 QObject::startTimer: Timers cannot be started from another thread,不知道它们与那个问题有关
  • 也许QGraphicsItem­­­­­­::setPos 使用了startTimer。您可以在 Qt 代码中搜索此消息并在此处设置断点以查看何时以及为何到达它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 2018-01-15
相关资源
最近更新 更多