首页 > 解决方案 > 如何将 QWidget 类中的 lineedit 字符串共享到工作线程

问题描述

现在我有一个 GUI 窗口,它接受几行用户输入并将它们插入到另一个导入的脚本的函数中。我需要在这个过程中添加线程,因为我将用户输入插入的功能可能需要很长时间并导致 GUI 变得无响应。这个 GUI 有一个主窗口和几个继承自 QWidget 类的其他窗口。下面显示的是我的导入和接受输入的窗口的代码。

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5.QtWidgets import QInputDialog, QFileDialog, QDialog
from PyQt5 import QtGui
from PyQt5.QtCore import Qt, QObject, QThread, pyqtSignal
import geopandas as gpd
from aw_widget import Ui_Areal_Weight
from areal_weight import arealwt

class aw(qtw.QWidget):    
    def __init__(self):
        super().__init__()
        self.ui = Ui_Areal_Weight()
        self.ui.setupUi(self)
        self.ui.aw_source_browse.clicked.connect(self.source_browser)
        self.ui.aw_target_browse.clicked.connect(self.target_browser)
        self.ui.aw_save_browse.clicked.connect(self.save_browser)
        self.ui.aw_run_prog.clicked.connect(self.run_aw)
        self.ui.aw_cancel_prog.clicked.connect(self.close_aw)
        title = "Areal Weighting Method"
        self.setWindowTitle(title)
    def source_browser(self):
        self.filename = QFileDialog.getOpenFileName()
        self.ui.aw_source_lineedit.setText(self.filename[0])  
    def target_browser(self):
        self.filename = QFileDialog.getOpenFileName()
        self.ui.aw_target_lineedit.setText(self.filename[0])    
    def save_browser(self):
        self.filename = QFileDialog.getSaveFileName()
        self.ui.aw_save_lineedit.setText(self.filename[0])              
    def run_aw(self):
        src = self.ui.aw_source_lineedit.text()
        target = self.ui.aw_target_lineedit.text()
        intp = self.ui.aw_intp_fields.text()
        intp = intp.split()
        suffix = self.ui.aw_output_suffix.text()
        save = self.ui.aw_save_lineedit.text()   
        try:
            src = gpd.read_file(src)
        except:
            qtw.QMessageBox.critical(self, 'Error', 'Invalid Source Shapefile')
            raise
        try:
            target = gpd.read_file(target)
        except:
            qtw.QMessageBox.critical(self, 'Error', 'Invalid Target Shapefile')
            raise            
        try:
            outp = arealwt(src, target, intp, suffix)
            outp.to_file(save)
            qtw.QMessageBox.information(self, 'Success', 'Areal Weighting Complete')
        except:
            qtw.QMessageBox.critical(self, 'Error', 'Interpolation Failed')
            raise                
    def close_aw(self):
        self.close()
    

图形界面窗口:
图形用户界面窗口

我的第一直觉是将 run_aw() 函数的内容移动到 aw 类之外的工作线程,但我不确定如何将 GUI 中的 lineedits 中的字符串共享给工作类,以便我可以插入将它们放入我的 areawt() 函数的参数中。基本上我希望用户填写所有字段,然后当他们单击运行时,lineedit 数据被发送到工作人员类并插入到 arealwt() 函数的参数中。在我看到的 QThread 示例中,需要很长时间处理的主函数被移至工作线程,但我还没有看到该函数依赖于用户输入 GUI 的信息的示例。

我的问题是,如何将 lineedit 字符串数据从我的 GUI 窗口发送到工作线程?

标签: pythonpyqt5qthread

解决方案


我能够通过从我的主类发出一个信号来解决这个问题,该信号包含我想传递给工人类的变量。我在工人类的函数中添加了一个装饰器,以便它可以接受字符串作为参数。

class aw_Worker(qtc.QObject):
    finished = qtc.pyqtSignal()
    
    @qtc.pyqtSlot(str,str,list,str,str)
    def worker_func(self, src, target, intp, suffix, save):
            src = gpd.read_file(src)
            target = gpd.read_file(target)
            outp = arealwt(src, target, intp, suffix)
            outp.to_file(save)
            self.finished.emit()


class aw(qtw.QWidget): 
    worker_requested = qtc.pyqtSignal(str,str,list,str,str)

    def __init__(self):
        super().__init__()
        self.ui = Ui_Areal_Weight()
        self.ui.setupUi(self)
        self.ui.aw_source_browse.clicked.connect(self.source_browser)
        self.ui.aw_target_browse.clicked.connect(self.target_browser)
        self.ui.aw_save_browse.clicked.connect(self.save_browser)
        self.ui.aw_run_prog.clicked.connect(self.run_aw)
        self.ui.aw_cancel_prog.clicked.connect(self.close_aw)
        title = "Areal Weighting Method"
        self.setWindowTitle(title)
        
    def source_browser(self):
        self.filename = QFileDialog.getOpenFileName()
        self.ui.aw_source_lineedit.setText(self.filename[0])

    def target_browser(self):
        self.filename = QFileDialog.getOpenFileName()
        self.ui.aw_target_lineedit.setText(self.filename[0])

    def save_browser(self):
        self.filename = QFileDialog.getSaveFileName()
        self.ui.aw_save_lineedit.setText(self.filename[0]) 
     
    def run_aw(self):
        # get data from gui
        src = self.ui.aw_source_lineedit.text()
        target = self.ui.aw_target_lineedit.text()
        intp = self.ui.aw_intp_fields.text()
        intp = intp.split()
        suffix = self.ui.aw_output_suffix.text()
        save = self.ui.aw_save_lineedit.text()
        
        # create thread
        self.thread = qtc.QThread()
        # create worker
        self.worker = aw_Worker()        
        # move worker to thread
        self.worker.moveToThread(self.thread)  
        
        # connect signals and slots 
        self.worker_requested.connect(self.worker.worker_func)        
        self.worker.finished.connect(self.thread.quit)        
               
        # start thread
        self.thread.start()
        
        # send data
        self.worker_requested.emit(src,target,intp,suffix,save)

推荐阅读