【发布时间】:2021-11-08 05:24:59
【问题描述】:
在过去的几天里,我一直在使用 PyQt5 为 GUI 构建一个相当简单的程序,但我遇到了以下问题,我似乎找不到解决方案。
这是我的代码的一个过度简化的版本(保持绝对基础以保持简短):
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)。然后使用docxtpl 和pdfplumber 库,对于每个选定的输入文件,我从中获取特定的文本片段并将它们放在模板文档中并将其保存为.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 用于定位我要查找的文本。
【问题讨论】:
-
这可能是画布被重绘的问题,而不是执行代码的问题。在 `toggleElemnts() 调用之后尝试 forcing a
repaint看看是否有帮助。 -
@bicarlsen 哇,它确实有效!我刚刚在第一个
self.toggleElements()之后添加了self.repaint(),它现在就像一个魅力。非常感谢! -
很高兴听到 :) 请接受答案,以便其他用户知道已找到解决方案。
-
@NikolasP。有没有机会
run_blueprint一个需要一些时间才能完成的功能?知道它的作用将真正帮助我们了解什么是真正的问题,这可能是repaint并没有真正解决的问题,因为在许多情况下,调用它实际上是一种解决方法,只是“隐藏”实际问题。 -
@musicamante 是的,它确实需要一些时间才能完成。取决于它正在处理的文件。我用来测试的文件大约需要 2 秒才能完成。