2011-05-30 101 views
1

我正在用python製作一個Qt GUI,並且出現錯誤:QObject :: startTimer:定時器不能從另一個線程啓動。它發生在我運行readModemSnap方法時。我一直在爲此工作了近一個星期,嘗試了許多不同的設計模式,用於在網絡上發現的Qt線程,但沒有成功。PyQt:定時器不能從另一個線程開始

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來啓動創建MainThread的UI,該MainThread在構建時自行啓動。當我評論線出來本地化的問題時,我發現它的時候,我在readModemSnap方法中調用self.refresh()和self.handleSnapshotResponse()。任何人都可以指出我做錯了什麼?或任何關於QThreading的教程?在此先感謝

+0

多線程GUI很難並且通常毫無意義。你爲什麼試試它?正常模式,可以工作的模式是在後臺線程上運行耗時的任務,但將所有GUI代碼移動到主GUI線程上。 – 2011-05-30 20:58:44

+0

檢查出http://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads,因爲它可能會有所幫助。 – synthesizerpatel 2011-06-02 07:45:17

回答

1

這是規則:你不能從除了運行Qt事件循環的主線程以外的任何線程調用任何GUI函數。當你看到有關QTimer的錯誤時,可能是因爲GUI中的某些東西在內部使用了一個定時器,並且正在從另一個線程觸發。

你的情況最可能的罪魁禍首就是你正在工作者線程上運行QGraphicsScene。我會嘗試重新排列,以便在響應newSnap信號時調用MainThread.reload中的代碼,而不是在它之前。