PyQt:不能从另一个线程启动计时器 [英] PyQt: timers cannot be started from another thread
问题描述
我正在使用python创建Qt GUI,但出现错误:QObject :: startTimer:无法从另一个线程启动计时器.当我运行readModemSnap方法时会发生这种情况.我已经进行了将近一个星期的尝试,尝试了许多我在Web上发现的Qt线程设计方法,但这些设计都不是什么.
I am making a Qt GUI with python and i am getting the error: QObject::startTimer: timers cannot be started from another thread. It occurs when I run the readModemSnap method. I've been working on this for almost a week trying many different design patterns for threading in Qt that i've found on the web but nothign works.
class ModemScopeWindow(QMainWindow, Ui_ModemScope):
def __init__(self, parent=None):
super(ModemScopeWindow, self).__init__(parent)
# Set up the user interface from Designer.
self.setupUi(self)
self.thread = MainThread()
"""
signal connections
"""
self.thread.newSnap.connect(self.updateScene)
self.thread.updateStatus.connect(self.setStatus)
self.thread.connectionLock.lock()
self.thread.runLock.lock()
self.connect(self.runButton, SIGNAL("clicked()"), self.thread.runLock.unlock, Qt.QueuedConnection)
self.connect(self.connectButton, SIGNAL("clicked()"), self.thread.connectionLock.unlock, Qt.QueuedConnection)
class MainThread(QThread):
newSnap = pyqtSignal(QGraphicsScene)
updateStatus = pyqtSignal(str)
initConnect = pyqtSignal()
def __init__(self, parent = None):
super(MainThread, self).__init__(parent)
self.samples = []
self.connectionLock = QMutex()
self.runLock = QMutex()
self.cliMute = QMutex()
self._displayCrosshairs = True
self._displayGrid = True
self.persistantMode = False
self.sampleDepth = 1
self._currentHaam = "4"
color = QColor(10,255,71)
self.plotPen = QPen(color)
self._leftXscene = -VIEW_SIZE/2
self._topYscene = -VIEW_SIZE/2
self._rightXscene = VIEW_SIZE/2
self._bottomYscene = VIEW_SIZE/2
self._leftXworld = -10.0
self._topYworld = 10.0
self._rightXworld = 10.0
self._bottomYworld = -10.0
self._scene = QGraphicsScene(self._leftXscene, self._topYscene, VIEW_SIZE, VIEW_SIZE, self)
self.start(QThread.HighestPriority)
def run(self):
self.updateStatus.emit("Enter target IP address and press Connect")
self.connectionLock.lock()
self.connectModem()
while(1):
self.runLock.lock()
#compile scene
self.readModemSnap()
self.newSnap.emit(self._scene)
self.runLock.unlock()
def readModemSnap(self):
self.updateStatus.emit("Reading Modem Snap...")
print len(self.samples)
if len(self.samples) >= self.sampleDepth:# and not self.persistantMode:
self.samples.pop(0)
self.cliMute.lock()
temp = cli.getModemSnap()
self.cliMute.unlock()
self.samples.append(temp)
self.cliMute.lock()
modType = cli.modemRead(80)
self.cliMute.unlock()
if((modType | 0x0FFFFFFF) == 0x0FFFFFFF):
modType = "0";
else:
modType = "%x"%modType
modType = str(modType)
modType = "0"
self.updateStatus.emit("Done")
self.refresh()
self._currentHaam = modType[0]
if self._displayGrid:
self.plotModulation(self._currentHaam)
self.handleSnapshotResponse()
self.updateStatus.emit("Ready to Run")
def refresh(self):
#delete scene
items = self._scene.items()
for x in items:
self._scene.removeItem(x)
#repaint the crosshairs
if self._displayCrosshairs:
self.plotLine(-VIEW_SIZE,0,+VIEW_SIZE,0, self.plotPen)
self.plotLine(0, -VIEW_SIZE,0, +VIEW_SIZE, self.plotPen)
self.plotScaleTicks()
#repaint grid
if self._displayGrid:
self.plotModulation(self._currentHaam)
self.newSnap.emit(self._scene)
def handleSnapshotResponse(self):
for x in range(len(self.samples)):
for sample in self.samples[x]:
upper = (sample >> 16) & 0xffff;
lower = sample & 0xffff
if (upper & 0x8000):
upper -= 0x10000
if (lower & 0x8000):
lower -= 0x10000
upper = float(upper)/128.0
lower = float(lower)/128.0
self.plot(upper, lower)
如您所见,我没有从另一个线程启动任何线程.我使用main来启动UI,该UI创建一个MainThread,该MainThread在构建时会自行启动.当我注释掉要定位的问题的代码时,我发现在readModemSnap方法中调用self.refresh()和self.handleSnapshotResponse()时发现了该问题.谁能指出我做错了什么方向?或有关QThreading的任何教程?预先感谢
as you can see Im not starting any thread from another thread. i use the main to start the UI which creates a MainThread that starts itself upon construction. When i commented lines out to localize the problem I found that its when i call self.refresh() and self.handleSnapshotResponse() in the readModemSnap method. Can anyone point me in the direction of what im doing wrong? or any tutorials on QThreading? thanks in advance
推荐答案
这是规则:除运行Qt事件循环的主线程以外,您不能从任何线程调用任何GUI函数.当您看到有关QTimer的错误时,可能是因为GUI中的某个内部使用了计时器,并且该计时器是从另一个线程触发的.
This is the rule: you cannot call any GUI functions from any thread other than the main thread running the Qt event loop. When you see errors about QTimer, it's probably because something in the GUI uses a timer internally and it is being triggered from another thread.
您遇到的最可能的罪魁祸首是您是通过工作线程在QGraphicsScene上进行操作的.我会尝试重新排列,以使MainThread.reload中的代码被调用以响应newSnap信号,而不是在响应之前.
The most likely culprit in your case is that you are operating on a QGraphicsScene from the worker thread. I would try rearranging such that the code in MainThread.reload is called in response to the newSnap signal, rather than before it.
这篇关于PyQt:不能从另一个线程启动计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!