从另一个线程调用setPos时,QGraphicsItem消失

时间:2015-10-11 15:54:26

标签: c++ multithreading qt qthread qgraphicsitem

我在QGraphicsItem­­­­­­上有两种类型的QGraphicsView 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,一切都正常。一旦我在自定义线程中调用它,蚂蚁就会消失。知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

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

你只需要:

  • Ant课程添加新信号(例如signalSetPos( QPoint pos )
  • Ant课程中添加新广告位(例如doSetPos( QPoint pos ))。此插槽实现只需调用setPos(pos)
  • 使用Qt::QueuedConnectionQt::BlockingQueuedConnectionconnect函数的第五个参数连接它们,对于GUI更新,Qt::QueuedConnection可能更好,因为它不会阻止您的线程)
  • 从您以前执行setPos( newPos )的主题中,只需发出signalSetPos( newPos )。然后,doSetPos将在主线程中执行(如果您使用Qt::QueuedConnection,则会立即执行Qt::BlockingQueuedConnection

查看此帖子,了解有关从线程发出信号的更多信息: Qt - emit a signal from a c++ thread