2014-05-20 2 views
0

내 HMI는 시작 및 중지, 스레드에서 GUI로 정보를 인쇄하는 필드 QStatusBar로 구성됩니다. "시작"할 때 중지 단추로 중단 할 수있는 스레드를 시작합니다. 내가하고 싶은 일은 스레드가 일시 중지 된 동안 사용자에게 선택권을주기 위해 스레드의 특정 지점에서 팝업 창을 여는 것입니다.PyQt : GUI에서 스레드로 정보 전송

from PyQt4 import QtCore, QtGui 
import sys 
import os 
import time 
from PyQt4.QtGui import QApplication, QDialog, QListWidgetItem, QListWidget, QIcon 
from test_bench_tool2 import Ui_MainWindow 
from popup import Ui_popup 

"""Class poppup window(continue/quit)""" 
class MyPopup(QtGui.QDialog): 
    def __init__(self,type): 
     super(MyPopup, self).__init__() 
     self.res = 0 
     self.type=type 
     self.ui = Ui_popup() 
     self.ui.setupUi(self) 
     QtCore.QObject.connect(self.ui.Quit,QtCore.SIGNAL("clicked()"),self.showDialogstop) 
     QtCore.QObject.connect(self.ui.Continue,QtCore.SIGNAL("clicked()"),self.showDialogcontinue) 

    def showDialogcontinue(self): 
     self.res=1 
     self.close() 
    def showDialogstop(self): 
     self.res=0 
     self.close() 


class MyThread(QtCore.QThread): 
    Statuschanged = QtCore.pyqtSignal(str) 
    popupmodechanged = QtCore.pyqtSignal(str) 
    def __init__(self, parent=None): 
     super(MyThread, self).__init__(parent=parent) 
     self.Status_auto = '' 
     self.dialog = MyPopup('toto') 
     self.Status_auto +='' 
     self.popup='' 
     self.answer='' 

    def run(self): 
     result = self.get_result() 

    def get_result(self,): 
     empty_result = [] 
     self.popup='Vn' 
     self.popupmodechanged.emit((self.popup)) 
     self.Status_auto +='\n\nMeasures finished!!' 
     self.Statuschanged.emit((self.Status_auto)) 
     results=[] 
     #do things to calculate results 
     return(results) 


class Main(QtGui.QDialog): 
    def __init__(self): 
     QtGui.QMainWindow.__init__(self) 
     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 
     # Connect the Buttons 
     QtCore.QObject.connect(self.ui.Start,QtCore.SIGNAL("clicked()"),self.Start) 
     QtCore.QObject.connect(self.ui.Stop,QtCore.SIGNAL("clicked()"),self.Stop) 
     self.__thread = MyThread(self) 
     self.__thread.Statuschanged.connect(self.ui.report_auto.setText) 
     self.__thread.popupmodechanged.connect(self.open_popup) 

    def open_popup(self): 
     self.__thread.dialog.__init__(self.__thread.dialog.type) 
     self.__thread.dialog.exec_() 

    def Start(self): 
     global tableRx, tableTx 
     self.ui.report_auto.setText('test in process...') 
     self.__thread.start() 

    def Stop(self): 
     self.ui.report_auto.setText('test canceled') 
     if self.__thread.isRunning(): 
      self.__thread.terminate() 

def main(): 

    app = QtGui.QApplication(sys.argv) 
    window = Main() 

    window.show() 
    sys.exit(app.exec_()) 

if __name__ == "__main__": 
    main() 

스레드를 계속하려면 팝업의 결과를 어떻게 얻을 수 있습니까? 나는이 같은 get_result() 함수를 넣으려고했다.

if self.dialog.res == 1: 
      print "continue" 
      self.dialog.close() 
      #do things 
     else: 
      self.dialog.close() 

그러나 나는 GUI에서 그 결과를 얻을 수 없다. GUI에서 내 스레드로 정보를 얻으려면 어떻게해야합니까 ?? 큐를 사용합니까?

+1

은 별도의 QThread에서 GUI를 (당신이 할 때 경고가 표시됩니다) 작성해서는 안됩니다. 대신 QThread에서 계산을 수행하고 스레드가 완료 될 때까지 기다린 다음 주 GUI 스레드에서 팝업을 엽니 다. – sebastian

+0

미안 해요,하지만 그게 내가하고 싶은게 아니에요, 팝업 스레드의 중간에 나타나야합니다,하지만 조언을 주셔서 감사합니다 –

답변

3

제 경험상 큐가 최상의 솔루션입니다. 스레드간에 정보를 공유하는 스레드 안전 방식입니다. 당신은 자신의 메인 클래스의 큐를 인스턴스화하고 스레드에 초기화 인수로 전달해야합니다 스레드 작업자 기능은 다음과 비슷한 모습이 될 것입니다 큐으로

#MyThread init 
def __init__(self, queue, parent=None): 
    #the input queue 
    self.in_queue = queue 
    #flag indicating if the thread's run function should actually run 
    self.running = True 
    super(MyThread, self).__init__(parent=parent) 
    self.Status_auto = '' 
    self.dialog = MyPopup('toto') 
    self.Status_auto +='' 
    self.popup='' 
    self.answer='' 

:이 또한

def run(self) 
    while self.running: #to keep the thread running 
     if not self.in_queue.empty(): 
      msg = self.in_queue.get() 
      #do something according to the message 
     else: 
      #do regular operation 

메시지 큐에 메시지 또는 무엇인가 'STOP'을 넣을 수 있습니다 (self.queue.put(value) 사용). 이 경우 큐의 get 메소드는 실제로 큐에서 무엇인가를 얻을 수있을 때까지 스레드를 차단합니다 (따라서 if). 큐가 Empty 예외가 발생합니다 empy 경우

msg = self.in_queue.get(block = False) 

이 방법 :이 동작을 변경할 수 있습니다. 당신은 아마도 스레드에서 이벤트 핸들러에 대화 상자에서 신호를 연결할 수 있습니다 위의 용액을 대신

from queue import Queue 
queue = Queue() 

하지만 난이 방법을 시도하지하고 것 거세한 숫양 확인되지 않은 :

는 큐 클래스에 액세스하려면 올바르게 작동.

이 방법으로 문제가 해결되기를 바랍니다.

건배, MATYAS

+0

Màtyàs 고마워, 아마 내 인생을 저장 :). 나는 가능한 한 빨리이 해결책을 연구 할 필요가 있고 immediatly 피드백을 주겠다. –

+0

미안하지만 나는 여전히 문제가있다. 계속 나를 도울 수 있니? 내 스레드에서 당신이 말한대로 self.in_queue = queue 선언 한 있지만 get_result() 사용할 때이 미친 오류 : Traceback (최근 호출 마지막) : 파일 "F : \ auto_bench \ materiel \ try4. py ", 줄 46, 실행 중 self.get_result() get_result의 파일"F : \ auto_bench \ materiel \ try4.py ", 줄 68, self.in_queue.put ('True') AttributeError : 'Main '객체에는 아무 것도 없습니다'put '스레드 객체에있는 반면 ?? 뭐가 문제 야? –

+0

in_queue가 실제로 Queue 객체인지 확인하십시오 (인쇄 만하면' '와 같은 내용을 보게됩니다). 매개 변수 이름이 문제를 일으킬 가능성이 있습니다 ('queue'는 또한 임포트 된 모듈을 참조하기 때문에), 다른 것을 "queue"보다는 매개 변수 이름으로 사용해보십시오. 또한 스레드를 인스턴스화 할 때 적절한 인수를 전달하는지 확인하십시오. 대기열 및 상위 매개 변수의 순서를 바꾼 것으로 보입니다. 오류 메시지는 "Main"유형의 객체에 "무언가를 넣으려고"한다는 것을 나타냅니다. –