Python中PyQt5与PyPDF2合并PDF时函数连接崩溃问题求助
问题分析与解决建议
嘿,我一眼就看出几个导致程序崩溃的关键问题,咱们一步步来解决:
核心问题
- 槽函数参数不匹配:Qt的
QPushButton.clicked信号默认会传递一个布尔值(表示按钮是否被按下),但你的laczeniePdf函数定义了需要两个参数g和h。当点击Start按钮时,信号只传一个参数,函数却要两个,直接触发参数错误导致崩溃。 - 未保存选中的文件信息:你的
openFile1和openFile2函数虽然返回了文件对象,但Qt的槽函数返回值会被完全忽略,这些文件对象根本没被保存下来,就算参数问题解决了,laczeniePdf也拿不到之前选中的文件。 - 文件对象生命周期问题:就算你能拿到返回的文件对象,Python的垃圾回收机制可能会在你调用
laczeniePdf前就把它关闭,导致读取PDF失败。
修复方案
咱们调整代码,用类的实例变量保存选中的文件路径(比保存文件对象更安全),修正槽函数参数,同时添加异常处理避免崩溃:
修改后的完整代码
import sys from PyQt5 import QtWidgets, QtCore import PyPDF2 class Ui_PolaczPliki(object): def setupUi(self, PolaczPliki): PolaczPliki.setObjectName("PolaczPliki") PolaczPliki.resize(295, 113) # 初始化实例变量,保存选中的文件路径 self.file_path1 = None self.file_path2 = None self.btnPlik1 = QtWidgets.QPushButton(PolaczPliki) self.btnPlik1.setGeometry(QtCore.QRect(30, 40, 91, 41)) self.btnPlik1.setObjectName("btnPlik1") self.btnPlik1.clicked.connect(self.openFile1) self.btnPlik2 = QtWidgets.QPushButton(PolaczPliki) self.btnPlik2.setGeometry(QtCore.QRect(160, 40, 91, 41)) self.btnPlik2.setObjectName("btnPlik2") self.btnPlik2.clicked.connect(self.openFile2) self.btnPlik3 = QtWidgets.QPushButton(PolaczPliki) self.btnPlik3.setGeometry(QtCore.QRect(80, 80, 40, 20)) self.btnPlik3.setObjectName("btnPlik3") self.btnPlik3.clicked.connect(self.laczeniePdf) self.label = QtWidgets.QLabel(PolaczPliki) self.label.setGeometry(QtCore.QRect(50, 10, 47, 13)) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(PolaczPliki) self.label_2.setGeometry(QtCore.QRect(180, 10, 47, 13)) self.label_2.setObjectName("label_2") self.retranslateUi(PolaczPliki) QtCore.QMetaObject.connectSlotsByName(PolaczPliki) def retranslateUi(self, PolaczPliki): _translate = QtCore.QCoreApplication.translate PolaczPliki.setWindowTitle(_translate("PolaczPliki", "Polacz pliki")) self.btnPlik1.setText(_translate("PolaczPliki", "Dodaj")) self.btnPlik2.setText(_translate("PolaczPliki", "Dodaj")) self.btnPlik3.setText(_translate("PolaczPliki", "Start")) self.label.setText(_translate("PolaczPliki", "Plik nr 1")) self.label_2.setText(_translate("PolaczPliki", "Plik nr 2")) def openFile1(self): pathFileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Wybierz plik', '', 'pdf(*.pdf)') print("PathFileName-'{}', \n_-'{}'".format(pathFileName, _)) if pathFileName: print("Wybrany plik: ", pathFileName) # 保存文件路径到实例变量,而不是返回文件对象 self.file_path1 = pathFileName def openFile2(self): pathFileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Wybierz plik', '', 'pdf(*.pdf)') print("PathFileName-'{}', \n_-'{}'".format(pathFileName, _)) if pathFileName: print("Wybrany plik: ", pathFileName) # 保存文件路径到实例变量 self.file_path2 = pathFileName def laczeniePdf(self): # 先检查是否选中了两个文件 if not self.file_path1 or not self.file_path2: QtWidgets.QMessageBox.warning(None, "Błąd", "Proszę wybrać oba pliki PDF!") return try: # 使用with语句自动管理文件,无需手动close with open(self.file_path1, 'rb') as f1, open(self.file_path2, 'rb') as f2, open('FinalOutput.pdf', 'wb') as output_file: reader1 = PyPDF2.PdfFileReader(f1) reader2 = PyPDF2.PdfFileReader(f2) writer = PyPDF2.PdfFileWriter() # 添加所有页面 for page in range(reader1.getNumPages()): writer.addPage(reader1.getPage(page)) for page in range(reader2.getNumPages()): writer.addPage(reader2.getPage(page)) writer.write(output_file) QtWidgets.QMessageBox.information(None, "Sukces", "Pliki zostały połączone pomyślnie!") except Exception as e: QtWidgets.QMessageBox.critical(None, "Błąd", f"Wystąpił błąd podczas łączenia: {str(e)}") if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) # 修正实例化错误,匹配当前类 ex = Ui_PolaczPliki() w = QtWidgets.QMainWindow() ex.setupUi(w) w.show() sys.exit(app.exec_())
关键修改点
- 添加了
self.file_path1和self.file_path2实例变量,用来保存用户选中的PDF路径,替代原来的返回值方式。 - 修改
laczeniePdf函数,去掉了多余的参数,直接从实例变量获取文件路径,符合Qt槽函数的调用规则。 - 使用
with语句管理文件,自动关闭文件句柄,避免资源泄漏。 - 添加了异常处理和用户提示:如果没选文件就点Start,会弹出警告;合并过程中出错会显示具体错误信息;成功后也会提示用户。
- 修正了主程序中的实例化错误(原来的
Ui_MainWindow改成了Ui_PolaczPliki,否则窗口不会正确显示)。
额外提示
如果你用的是较新版本的PyPDF2,PdfFileReader和PdfFileWriter已经被标记为过时,推荐使用PdfReader和PdfWriter,用法基本一致,只需要替换类名即可:
reader1 = PyPDF2.PdfReader(f1) reader2 = PyPDF2.PdfReader(f2) writer = PyPDF2.PdfWriter()
内容的提问来源于stack exchange,提问作者memo747
相关产品推荐
相关产品推荐

