从线程更新场景?

时间:2014-07-14 18:23:52

标签: multithreading qt qgraphicsview qgraphicsscene

我需要从帖子中使用QGraphicsView更新QGraphicsScene

下面是我正在做的一些伪问题代码示例,它导致了我的问题(运行时错误)。

我做错了什么,我该怎么做?

主要应用程序:

void Main::startThread()
{
  view = new QGraphicsView(...);
  thread = new MyThread(...);
  connect(thread, SIGNAL(doSceneUpdate(QGraphicsScene*)), this, SLOT(updateScene(QGraphicsScene*)));
  thread->start();
}

void Main::updateScene(QGraphicsScene *scene)
{
  view->SetScene(scene);
  view->show();
  repaint();
}

线程:

void MyThread::run()
{
  QGraphicsScene *scene = new QGraphicsScene(...);
  while(1)
  {
    //draw stuff on the scene
    emit doSceneUpdate(scene);
    //some delay
  }

提前致谢!!!

[编辑] 错误是:

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread
3e53c0. Receiver '' (of type 'QGraphicsScene') was created in thread 1476cd18", file c:\Qt\qt-everywhere-opensource-src-4.8.2\src\corelib\kernel\qcoreapplication.cpp, line 501

3 个答案:

答案 0 :(得分:1)

问题在于您的连接线。您正在将插槽连接到没有意义的信号。您应该将信号从线程连接到插槽:

connect(thread, SIGNAL(doSceneUpdate(QGraphicsScene*)),this, SLOT(updateScene(QGraphicsScene*)));

答案 1 :(得分:1)

in

void MyThread::run()
{
  QGraphicsScene *scene = new QGraphicsScene(...);
  ...

}

您是否将this传递给QGraphicsScene()的构造函数?

这可能是导致错误的原因之一,因为现在您将MyThread的孩子传递给Main

尝试在堆栈上创建QGraphicsScene对象,或者将父对象创建为NULL(new QGraphicsScene(0)

答案 2 :(得分:1)

  

我做错了什么,我该怎么做?

我认为规范的答案是here - 简而言之,文章指出你不应该将QThread子类化,而是应该使用"裸" (即未子类化)QThread对象并将其started()信号连接到一个槽,然后在线程启动后将在该线程的上下文中运行。这样就可以自动处理对象线程所有权问题。

另请注意,除了主Qt线程之外的线程通常不允许直接创建或与QGraphicsScene等GUI对象交互,因为这样做会引入竞争条件,因为Qt'中的操作同时进行。的GUI事件循环。如果你想使用一个单独的线程,你需要远离你的GUI对象,而只是让它发出异步信号和/或将事件发送到主/ GUI线程以获得主/ GUI线程代表它进行GUI对象更新。