PyQt5 在 class' 方法中调用静态方法会打乱方法代码的执行顺序
PyQt5 Calling a static method inside a class' method messes up the execution order of the method's code
过去几天我一直在为 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())
假设我已经 select 编辑了 listWidget
中的一个项目,并且还在 selected_files_directories[]
变量中存储了一个文件路径列表。
如果我按原样 运行 代码,当 processFiles(self)
到 运行 时,我会遇到一些奇怪的行为。由于某种原因,for 循环首先是 运行,然后是第一个 toggleElements()
,然后是第二个 toggleElements()
。这导致我想暂时禁用这两个元素,直到 for 循环结束并一直保持启用状态。
但是,如果我根本不调用 run_blueprint(file)
方法,而是 运行 for 循环内的任何其他代码,甚至完全放弃循环,那么这两个元素将首先被禁用,然后是其余代码 运行s,最后它们再次启用。
我认为问题与我在 class 之外调用静态方法有关。你对如何解决这个问题有什么想法吗?提前致谢!
编辑: 下面是 run_blueprint()
函数的简化版本。
该程序的基本功能如下:我 select 模板文件 (.docx)
和输入文件 (.pdf)
。然后使用 docxtpl
和 pdfplumber
库,对于每个 selected 输入文件,我从中获取特定的文本片段并将它们放在模板文档中并将其另存为 .docx 文件.
在下面的代码中,假设 template_path
和 bp_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
蓝图代码通常包含 API 调用,需要几毫秒才能发送响应。除此之外,它主要 regex
用于定位我正在寻找的文本片段。
这是重绘 canvas 的问题。在 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 的评论建议获取更多上下文并帮助澄清:
重绘 canvas 没有问题。问题是函数阻塞了主线程。根据上下文,更好的解决方案是将阻塞任务卸载到 QThread
or QProcess
以解锁主线程。
过去几天我一直在为 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())
假设我已经 select 编辑了 listWidget
中的一个项目,并且还在 selected_files_directories[]
变量中存储了一个文件路径列表。
如果我按原样 运行 代码,当 processFiles(self)
到 运行 时,我会遇到一些奇怪的行为。由于某种原因,for 循环首先是 运行,然后是第一个 toggleElements()
,然后是第二个 toggleElements()
。这导致我想暂时禁用这两个元素,直到 for 循环结束并一直保持启用状态。
但是,如果我根本不调用 run_blueprint(file)
方法,而是 运行 for 循环内的任何其他代码,甚至完全放弃循环,那么这两个元素将首先被禁用,然后是其余代码 运行s,最后它们再次启用。
我认为问题与我在 class 之外调用静态方法有关。你对如何解决这个问题有什么想法吗?提前致谢!
编辑: 下面是 run_blueprint()
函数的简化版本。
该程序的基本功能如下:我 select 模板文件 (.docx)
和输入文件 (.pdf)
。然后使用 docxtpl
和 pdfplumber
库,对于每个 selected 输入文件,我从中获取特定的文本片段并将它们放在模板文档中并将其另存为 .docx 文件.
在下面的代码中,假设 template_path
和 bp_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
蓝图代码通常包含 API 调用,需要几毫秒才能发送响应。除此之外,它主要 regex
用于定位我正在寻找的文本片段。
这是重绘 canvas 的问题。在 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 的评论建议获取更多上下文并帮助澄清:
重绘 canvas 没有问题。问题是函数阻塞了主线程。根据上下文,更好的解决方案是将阻塞任务卸载到 QThread
or QProcess
以解锁主线程。