PyQt5在类的方法中调用静态方法会打乱方法代码的执行顺序

2024-09-30 10:30:38 发布

您现在位置:Python中文网/ 问答频道 /正文

在过去的几天里,我一直在为GUI使用PyQt5构建一个相当简单的程序,我遇到了以下问题,我似乎找不到解决方案

下面是我的代码的一个过于简化的版本(保留了绝对的基础以保持简短):

def run_blueprint(file):
    # doing stuff to the file and returning the path to the output file
    return full_path


class Window(QMainWindow, Ui_MainWindow):
    # some variables here

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.connectSignalsSlots()

    def connectSignalsSlots(self):
        self.pushButton.clicked.connect(self.processFiles)

    def processFiles(self):
        self.toggleElements()
        for i, file in enumerate(self.selected_files_directories):
            temp_full_path = run_blueprint(file)
            self.listWidget_3.insertItem(i, temp_full_path)
        self.toggleElements()

    def toggleElements(self):
        self.pushButton_2.setEnabled(not self.pushButton_2.isEnabled())
        self.listWidget.setEnabled(not self.listWidget.isEnabled())


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    sys.exit(app.exec())

假设我已经从listWidget中选择了一个项,并且在selected_files_directories[]变量中存储了一个文件路径列表

如果我按原样运行代码,当processFiles(self)开始运行时,我会出现一些奇怪的行为。出于某种原因,For循环首先运行,然后是第一个toggleElements(),然后是第二个toggleElements()。这将导致我想暂时禁用的两个元素,直到for循环在整个时间内都处于启用状态

但是,如果我根本不调用run_blueprint(file)方法,而是在for循环中运行任何其他代码,甚至完全放弃循环,那么这两个元素将首先被禁用,然后运行其余代码,最后再次启用

我相信这个问题与我在类外调用静态方法有关。你对如何解决这个问题有什么想法吗?提前谢谢


编辑:下面是run_blueprint()函数的简化版本。 这个程序的基本功能如下:我选择一个模板文件(.docx)和输入文件(.pdf)。然后使用docxtplpdfplumber库,对于每个选定的输入文件,我从中获取特定的文本片段,并将它们放在模板文档中,并将其另存为.docx文件

在下面的代码中,假设template_pathbp_path分别显示模板文件和蓝图文件的路径

def run_blueprint(file):
    doc = DocxTemplate(template_path) # docxtpl method
    global lns
    lns = export_data(file) # function I made that uses pdfplumber to get all the text from a pdf file

    global context
    context = {}

    with open(bp_path, 'r', encoding='utf8') as f:
        blueprint = f.read() # blueprint contains python code that populates the context variable. I do it this way to easily change between blueprints
    exec(blueprint, globals(), locals()) # I know it's not a good practice to use exec but it's intended for personal use

    doc.render(context) # docxtpl method
    output_path = "D:\\Desktop" # could be any path
    doc.save(output_path) # docxtpl method
    return output_path

blueprint代码通常包含需要几毫秒时间发送响应的API调用。除此之外,它主要用于定位我正在寻找的文本片段


Tags: 文件thetopathrun代码selffor
1条回答
网友
1楼 · 发布于 2024-09-30 10:30:38

这是重新绘制画布时出现的问题。在toggleElements调用之后添加repaint调用

def processFiles(self):
    self.toggleElements()
    self.repaint()
    
    for i, file in enumerate(self.selected_files_directories):
        temp_full_path = run_blueprint(file)
        self.listWidget_3.insertItem(i, temp_full_path)
    
    self.toggleElements()

更多基于@musicamante评论建议的内容,并帮助澄清: 重新绘制画布时没有问题。问题是函数阻塞了主线程。给定上下文,更好的解决方案是将阻塞任务卸载到^{}^{}以取消阻塞主线程

相关问题 更多 >

    热门问题