简体   繁体   English

PyQt4:不能从另一个线程启动计时器

[英]PyQt4: timers cannot be started from another thread

When I run the following code ... 当我运行以下代码时...

import sys, time
from PyQt4 import QtCore, QtGui

class WorkThread(QtCore.QThread):
 def __init__(self):
  QtCore.QThread.__init__(self)

 def run(self):
  for i in range(100):
   time.sleep(1) # artificial time delay
   print(i)
   test.pbar.setValue(i)
  return


class MyApp(QtGui.QWidget):
 def __init__(self):
  QtGui.QWidget.__init__(self, None)
  self.setGeometry(300, 300, 280, 600)
  self.setWindowTitle('threads')
  self.layout = QtGui.QVBoxLayout(self)
  self.pbar = QtGui.QProgressBar(self)
  self.layout.addWidget(self.pbar)



# run
app = QtGui.QApplication(sys.argv)
test = MyApp()
workThread = WorkThread()
workThread.start()
test.show()
app.exec_()

I get the following error ... 我收到以下错误...

QObject::startTimer: timers cannot be started from another thread

The code still continues to execute ok, but what I dont understand is why this error stops appearing after I remove test.pbar.setValue(i) OR replace pbar with a different widget such as a list. 代码仍然可以继续执行,但是我不明白的是为什么在删除test.pbar.setValue(i)或用其他小部件(例如列表test.pbar.setValue(i)替换pbar 后,此错误不再出现 It seems obvious that the error is specific to the progressbar widget ... 似乎很明显,该错误是特定于progressbar小部件的。

As I mentioned in my comment, the error you're seeing provides you exactly with the information it was meant to provide. 正如我在评论中提到的那样,您所看到的错误为您提供了原本应提供的信息。 You are not allowed to invoke QObject::setTimer from a thread different from the one in which the timer was created. 不允许从与创建计时器不同的线程调用QObject::setTimer Specifically, one version of the code of QObject I found has this code: 具体来说,我发现的QObject代码的一个版本包含以下代码:

int QObject::startTimer(int interval)
{
    Q_D(QObject);

    if (interval < 0) {
        qWarning("QObject::startTimer: QTimer cannot have a negative interval");
        return 0;
    }

    d->pendTimer = true;                                // set timer flag

    if (!d->threadData->eventDispatcher) {
        qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
        return 0;
    }
    return d->threadData->eventDispatcher->registerTimer(interval, this);
}

Note the warning-generating code. 注意警告生成代码。

Calling the pbar.setValue method obviously makes a call to this startTimer method, which creates the warning. 显然,调用pbar.setValue方法会调用此startTimer方法,从而创建警告。

Now, I'm not sure what your problem with this is? 现在,我不确定您的问题是什么? Do you absolutely need to control the progress bar directly from another thread? 您是否绝对需要直接从另一个线程控制进度栏? That's not a good idea. 那不是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM