2017-09-04 40 views
0

附加程序引發這些錯誤:PySide/PyQtGraph進入主Qt的事件線程

的QPixmap:這是不是安全使用GUI線程之外的像素映射

的QObject :: startTimer所:定時器不能從啓動另一個線程

import sys 
import PySide 
import numpy as np 
import pyqtgraph as pg 
import threading 

from PySide import QtGui, QtCore 
from PySide.QtGui import * 
from PySide.QtCore import * 
from ui_mainWindow import Ui_MainWindow 

#------------------------------------------------------------------------------- 
# Main Window Class 
# handle events and updates to the Qt user interface objects 
#------------------------------------------------------------------------------- 
class MainWindow(QMainWindow, Ui_MainWindow): 

    def __init__(self): 
     super(MainWindow, self).__init__() 
     self.setupUi(self) 
     self.setup_actions() 
     self.show() 

    def setup_actions(self): 
     self.startScopeButton.clicked.connect(self.start_stop_scope) 

    def start_stop_scope(self): 
     print("starting scope") 
     self.scope_display_thread() 

    def scope_display_thread(self): 
     threading.Thread(target=self._scope_display_thread).start() 

    def _scope_display_thread(self): 
     global data_ch1  
     data_ch1 = np.random.normal(0, 10, 1000) 
     self.graphicsView.plot(data_ch1,clear=True) 

#------------------------------------------------------------------------------- 
# Main Application Start Point 
#------------------------------------------------------------------------------- 

def main(): 
    app = QApplication(sys.argv) 
    mainWin = MainWindow() 
    ret = app.exec_() 
    sys.exit(ret) 

data_ch1 = [] 
main() 

這是我試圖做的簡化版本..即有一個線程接收和繪圖數據。從搜索論壇等,我從根本上知道問題是,我必須更新從「主要Qt事件線程」的情節..但我不知道如何做到這一點。我的代碼的幾個信號插槽排列看起來很有前途,但只會導致程序崩潰。我是一個改革過的C#人;-)在C#或Java中,通常我會在繪圖方法重寫中執行繪圖,然後在剛剛創建新數據時強制重繪應用程序加載英寸似乎PyQtGraph.plot()試圖立即畫?我可以異步添加數據,然後告訴主線程重新繪製場景?

謝謝!

+0

什麼是'graphicsView'? – eyllanesc

回答

0

當您對您的問題發表評論時,您只能在主線程中更新GUI,那麼針對此類問題的策略是將輔助線程的數據發送到主要通過信號。

的信號可以攜帶一些數據,但這些都必須在其創建時表示,創建它的方法如下:

signal = QtCore.Signal(type_1, type_2, ..., type_n) 

你的具體情況np.random.normal (0, 10, 1000)np.ndarray,這很容易被獲得執行以下:

print(type(np.random.normal (0, 10, 1000))) 

輸出:

<class 'numpy.ndarray'> 

或者我們可以使用object,因爲所有類都從該基類繼承。然後我們將該信號與繪製的函數連接起來,在這種情況下,我們將使用如下所示的lambda函數:

class MainWindow(QtGui.QMainWindow, Ui_MainWindow): 
    signal = QtCore.Signal(np.ndarray) # or signal = QtCore.Signal(object) 

    def __init__(self): 
     [..] 
     self.show() 

     self.signal.connect(lambda data: self.graphicsView.plot(data, clear=True)) 

    [...] 

    def _scope_display_thread(self): 
     data_ch1 = np.random.normal(0, 10, 1000) 
     self.signal.emit(data_ch1) 
+0

非常好。謝謝您的幫助。我有一種感覺,這也會幫助其他人。儘管我理解了基本問題,但對於我來說,找到正確的方法有點蠻荒。 –

+0

請不要忘記標記我的答案是正確的 – eyllanesc