简体   繁体   English

PyQt-另一个线程中的对话框

[英]PyQt - Dialog in another thread

my program has a main window and in this window it runs a thread to read the power from a photodetector then it sends a signal, which is captured by a slot in the main window that updates the main window's gui. 我的程序有一个主窗口,在该窗口中,它运行一个线程以从光电探测器读取电源,然后发送一个信号,该信号由主窗口中的插槽捕获,该插槽会更新主窗口的gui。

Then I have another widget (let's call it programming widget) that pops from the main window, which is basically a plain text into which the user can insert commands so the program will execute them. 然后,我还有另一个从主窗口弹出的小部件(我们称其为编程小部件),它基本上是纯文本,用户可以在其中插入命令,以便程序执行它们。 Now the issue comes: 现在问题来了:

When I just open the programming widget with "show", the main window keeps updating the photodetector. 当我仅使用“ show”打开编程小部件时,主窗口将不断更新光电探测器。 However, when I start executing a sequence from the programming widget the main window freezes and the photodetector readings stops with it while is executing the commands (I guess it keeps reading because is in another thread but it stops updating the main window's gui). 但是,当我开始从编程小部件执行序列时,主窗口冻结,并且在执行命令时光电探测器的读数随之停止(我猜它一直在读取,因为在另一个线程中,但它停止更新主窗口的gui)。

My question is: The programming widget is already, by default, in another thread since the main window keeps working when it's popped. 我的问题是:默认情况下,编程小部件已经在另一个线程中,因为当弹出主窗口时,它一直处于工作状态。 So, why it (main window)freezes when the programming widget is in a loop? 那么,为什么在编程小部件处于循环中时,它(主窗口)会冻结?

Here is the Thread code: 这是线程代码:

class PDThread(QtCore.QThread):

valueupdate = QtCore.pyqtSignal(float)
state = 1

def __init__(self, state, port):
    QtCore.QThread.__init__(self)
    self.photodetector = PM100D()
    self.port = port

def run(self):
        while True:
            try:
                self.photodetector.connect(self.port)
                break
            except:
                self.dialog = dialog_classes.DialogPort()
                self.dialog.set_instrument('PM100D')
                self.dialog.exec_()
                ret = self.dialog.pm100d.itemText(self.dialog.pm100d.currentIndex())
                if ret == QtGui.QDialog.Accepted:
                    self.port = str(ret)
                else:
                    self.photodetector.__del__()
                    self.quit()
                    return

        window.PDState = 1
        window.startpd.setText('Stop PD')     
        while self.state == 1:
            time.sleep(0.1)
            value = self.photodetector.get_pow()
            self.valueupdate.emit(value)

Here is the function that creates the thread and the slot in the main window: 这是在主窗口中创建线程和插槽的函数:

def ActionConnect_PM100D(self):
    if self.PDState == 0:
        self.PD = PDThread(self.PDState, self.PDport)
        self.PD.valueupdate.connect(self.PDHandler)
        self.threads = []
        self.threads.append(self.PD)
        self.PD.start()
    else:
        self.PDState = 0
        self.PD.state = 0
        self.startpd.setText('Start PD')


def PDHandler(self, value):
    ref = float(self.refpd.value())
    self.outputpd.setText(str(value-ref))

Here also in the main window, the function that creates the widget: 这也是在主窗口中,创建小部件的函数:

    def ActionSetup(self):
    self.program = dialog_classes.Programming(self.newport, self.output, self.outputpd)
    self.program.show()

Finally, the widget code: 最后,小部件代码:

class Programming(QtGui.QDialog, Ui_Programming_Dialog, gui.MyApp):

def __init__(self, ESP300, output, outputpd):
    QtGui.QDialog.__init__(self)
    self.setupUi(self)
    self.setWindowTitle('Programming Setup')
    self.openbuttom.clicked.connect(self.Open)
    self.save.clicked.connect(self.Save)
    self.execute.clicked.connect(self.Execute)
    self.newport = ESP300
    self.output = output
    self.outputpd = outputpd

def Open(self):
    self.fileName = QtGui.QFileDialog.getOpenFileName(self, 'OpenFile', '', '*.txt')
    try:
        text = open(self.fileName).read()
    except:
        None
    else:
        self.program.setPlainText(text)

def Save(self):
    self.fileName = QtGui.QFileDialog.getSaveFileName(self, 'Save File', '', '*.txt')
    try:
        open(self.fileName, 'w').write(str(self.program.toPlainText()))
    except:
        None

def Execute(self):
    text = str(self.program.toPlainText())
    lines = text.split('\n')
    for line in lines:
        arg = []
        List = line.split(',')
        for word in List:
            arg.append(word.strip())

        if arg[0].lower() == 'move':
            if arg[1].lower() == 'x':
                self.newport.move_x(float(arg[2]))
            elif arg[1].lower() == 'y':
                self.newport.move_y(float(arg[2]))
            elif arg[1].lower() == 'z':
                self.newport.move_z(float(arg[2]))
        elif arg[0].lower() == 'wait':
            self.newport.wait()
        elif arg[0].lower() == 'home':
            self.newport.home()
            while True:
                try:
                    self.GetPosition()
                except:
                    time.sleep(0.5)
                else:
                    if self.newport.x == 0 and self.newport.y == 0 and self.newport.z == 0:
                        break
        elif arg[0].lower() == 'power on':
            self.newport.power_on(arg[1])
        elif arg[0].lower() == 'power off':
            self.newport.power_off(arg[1])
        elif arg[0].lower() == 'pos':
            self.newport.pos_x(arg[1])
            self.newport.pos_y(arg[2])
            self.newport.pos_z(arg[3])
            while True:
                try:
                    self.GetPosition()
                except:
                    time.sleep(0.5)
                else:
                    time.sleep(1)
                    break
        elif arg[0].lower() == 'get pos':
            self.GetPosition()
        elif arg[0].lower() == 'get error':
            self.GetError()
        elif arg[0].lower() == 'get pow':
            print(self.outputpd.toPlainText())

        time.sleep(2)


def closeIt(self):
    self.close()

Thank you for your support. 谢谢您的支持。

Generally, the way this is done is to create a class derived from QObject that handles all the non-Qt data collection and move that into a separate thread using the worker model . 通常,完成此操作的方法是创建一个从QObject派生的类,该类处理所有非Qt数据收集,并使用worker模型将其移至单独的线程中。

Then, you can use signals to pass data back and forth between the main (GUI) thread and the Worker thread, and to trigger events (like popping up a dialog in the main thread because of an event in the worker thread). 然后,您可以使用信号在主(GUI)线程和辅助线程之间来回传递数据,并触发事件(例如由于辅助线程中的事件而在主线程中弹出对话框)。

I tried moving the Execute method to another thread using the worker model as suggested but it also froze the gui, I don't know why. 我尝试按照建议的方式使用工作器模型将Execute方法移动到另一个线程,但是它也冻结了gui,我不知道为什么。 Probably I did something wrong. 可能我做错了。

However, when I created another thread directly in the Class implemented to execute the loop and it worked. 但是,当我直接在实现了执行循环的Class中创建另一个线程时,它起作用了。 I followed this example: https://nikolak.com/pyqt-threading-tutorial/ 我遵循以下示例: https : //nikolak.com/pyqt-threading-tutorial/

In addition, here is my code. 另外,这是我的代码。 I hope it can help others as well, thank you. 我希望它也可以帮助其他人,谢谢。

self.worker_thread = []

def Execute(self):
    self.execution = ProgramExecution(self.newport, self.output, self.outputpd, self.program)
    self.worker_thread.append(self.execution)
    self.execution.start()

And here is the Thread Class: 这是线程类:

class ProgramExecution(QtCore.QThread):

_signalStatus = QtCore.pyqtSignal(str)

def __init__(self, ESP300, output, outputpd, program):
    QtCore.QThread.__init__(self)
    self.newport = ESP300
    self.output = output
    self.outputpd = outputpd
    self.program = program

def __del__(self):
    self.wait()

def run(self):
    text = str(self.program.toPlainText())
    lines = text.split('\n')
    for line in lines:
        arg = []
        List = line.split(',')
        for word in List:
            arg.append(word.strip())

        if arg[0].lower() == 'move':
            if arg[1].lower() == 'x':
                self.newport.move_x(float(arg[2]))
            elif arg[1].lower() == 'y':
                self.newport.move_y(float(arg[2]))
            elif arg[1].lower() == 'z':
                self.newport.move_z(float(arg[2]))
        elif arg[0].lower() == 'wait':
            self.newport.wait()
        elif arg[0].lower() == 'home':
            self.newport.home()
            while True:
                try:
                    self.GetPosition()
                except:
                    time.sleep(0.5)
                else:
                    if self.newport.x == 0 and self.newport.y == 0 and self.newport.z == 0:
                        break
        elif arg[0].lower() == 'power on':
            self.newport.power_on(arg[1])
        elif arg[0].lower() == 'power off':
            self.newport.power_off(arg[1])
        elif arg[0].lower() == 'pos':
            self.newport.pos_x(arg[1])
            self.newport.pos_y(arg[2])
            self.newport.pos_z(arg[3])
            while True:
                try:
                    self.GetPosition()
                except:
                    time.sleep(0.5)
                else:
                    time.sleep(1)
                    break
        elif arg[0].lower() == 'get pos':
            self.GetPosition()
        elif arg[0].lower() == 'get error':
            self.GetError()
        elif arg[0].lower() == 'get pow':
            print(self.outputpd.toPlainText())

        time.sleep(2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM