2014-05-20 193 views
0

我的HMI由2个按钮组成:Start和Stop,还有一个字段QStatusBar,用于将信息从线程打印到GUI。当我做“开始”时,我启动一个线程,我可以用停止按钮中断。 我想要做的是在线程中的某个点打开一个弹出窗口,以便在线程暂停时为用户提供选择。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获取信息到我的线程?我有tu使用队列吗?

+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 

这也允许您在消息队列中放置(使用self.queue.put(value)'STOP'消息或其他内容。 请注意,在这种情况下,队列的get方法会阻塞线程,直到它实际上可以从队列中获取某些内容(因此if)。如果队列empy的Empty将引发异常

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

这样:你可以改变这种行为。

访问队列类:

from queue import Queue 
queue = Queue() 

代替上述解决方案的你可能从信号对话框中的线程连接到事件处理程序,但我还没有试过这样的,不知道羯羊它会好好工作。

我希望这可以解决您的问题。

干杯, 的Mátyás

+0

非常感谢Màtyàs,你可能会拯救我的生命:)。我需要尽快研究这个解决方案,我立刻给你反馈 –

+0

对不起,我已经尝试过,并重试我仍然有问题。你能继续帮助我吗?在我的线程中,我已经声明self.in_queue = queue,正如你所说的,但是当我在get_result()中使用它时,我有这个疯狂的错误:Traceback(最近调用最后一次): 文件“F:\ auto_bench \ materiel \ try4。 py“,第46行,运行 self.get_result() get_result中的第68行文件”F:\ auto_bench \ materiel \ try4.py“ self.in_queue.put('True') AttributeError:'Main '对象没有属性'放' 而我在线程对象?怎么了? –

+0

确保in_queue实际上是一个Queue对象(只需将其打印出来,您应该看到类似'_memoryaddress_>'处的