python 尝试引用Qlistwidget并得到“预期的str、bytes或os.PathLike对象,而不是ListWidget”错误

mxg2im7a  于 2023-03-28  发布在  Python
关注(0)|答案(2)|浏览(118)

我是新的编程,并一直在努力学习python为这些过去的几个星期.我偶然发现this视频,并试图使similiar的事情,但我想添加新的功能,我可以批量合并所有的子文件夹pdf到自己的pdf.添加路径到文件夹和添加新的方法后,我从this用户我得到了一个错误,说列表小部件不是str.

import sys, os
if hasattr(sys, 'frozen') :
    os.environ['path'] = sys.MEIPASS + ";" + os.environ['path']
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QListWidget, \
    QVBoxLayout, QHBoxLayout, QGridLayout, \
    QDialog, QFileDialog, QMessageBox, QAbstractItemView
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtGui import QIcon
from PyPDF2 import PdfMerger, PdfReader

def resource_path(relative_path) :
    try:
        base_path = sys._MEIPASS
    except Exception :
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

class ListWidget(QListWidget) :
    def __init__(self, parent=None):
        super().__init__(parent=None)
        self.setAcceptDrops(True)
        self.setStyleSheet('''font-size: 25px;''')
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
    
    def dragEnterEvent(self, event) :
        if event.mimeData().hasUrls():
            event.accept()
        else:
            return super().dragEnterEvent(event)

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            return super().dragMoveEvent(event)

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
            
            pdfFiles=[]
            
            for url in event.mimeData().urls():
                if url.isLocalFile():
                    if url.toString().endswith('.pdf'):
                        pdfFiles.append(str(url.toLocalFile()))
            self.addItems(pdfFiles)
        else:
            return super().dropEvent(event)
        
class output_field(QLineEdit) :
    def __init__(self):
        super().__init__()
        self.height = 55
        self.setStyleSheet('font-size: 30px;')
        self.setFixedHeight(self.height)

    def dragEnterEvent(self, event) :
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
            
            if event.mimeData().urls():
                self.setText(event.mimeData().urls()[0].toLocalFile())

        else:
            event.ignore()

class output_field(QLineEdit) :
    def __init__(self):
        super().__init__()
        self.height = 55
        self.setStyleSheet('font-size: 30px;')
        self.setFixedHeight(self.height)

    def dragEnterEvent(self, event) :
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
            
            if event.mimeData().urls():
                self.setText(event.mimeData().urls()[0].toLocalFile())

        else:
            event.ignore()

class button(QPushButton):
    def __init__(self, label_text):
        super().__init__()
        self.setText(label_text)
        self.setStyleSheet('''
            font-size: 30px;
            width: 180px;
            height: 50px;
        ''')   

class PDFApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('PDF FILE MERGE')
        self.setWindowIcon(QIcon(resource_path('alice.ico')))
        self.resize(1800, 800)
        self.initUI()
    
    def initUI(self):
        mainLayout = QVBoxLayout()
        outputFolderROw = QHBoxLayout()
        buttonLayout = QHBoxLayout()

        self.outputFIle = output_field()
        outputFolderROw.addWidget(self.outputFIle)

        self.buttonBrowseOutputFile = button('&save to')
        self.buttonBrowseOutputFile.clicked.connect(self.populateFileName)
        outputFolderROw.addWidget(self.buttonBrowseOutputFile)

    def initUI(self):
        mainLayout = QVBoxLayout()
        outputFolderROw = QHBoxLayout()
        buttonLayout = QHBoxLayout()

        self.outputFIle = output_field()
        outputFolderROw.addWidget(self.outputFIle)

        self.buttonBrowseOutputFile = button('&save to')
        self.buttonBrowseOutputFile.clicked.connect(self.populateFileName)
        outputFolderROw.addWidget(self.buttonBrowseOutputFile)
        """
        # listbox widget
        """
    
        self.pdfListWidget = ListWidget(self)
        """
        Buttons
        """
        self.buttonBrowseinputFile =button('&Folder')
        self.buttonBrowseinputFile.clicked.connect(self.addFolderPath)
        buttonLayout.addWidget(self.buttonBrowseinputFile)

        self.buttonDeleteSelect =button('&Delete')
        self.buttonDeleteSelect.clicked.connect(self.deleteSelected)
        buttonLayout.addWidget(self.buttonDeleteSelect)

        self.buttonMerge = button('&merge')
        self.buttonMerge.clicked.connect(self.mergeFile)
        buttonLayout.addWidget(self.buttonMerge)

        self.buttonBatchMerge = button('&batch merge')
        self.buttonBatchMerge.clicked.connect(self.batch_merge)
        buttonLayout.addWidget(self.buttonBatchMerge)

        self.buttonClose = button('&close')
        self.buttonClose.clicked.connect(QApplication.quit)
        buttonLayout.addWidget(self.buttonClose)

        self.buttonReset = button('&Reset')
        self.buttonReset.clicked.connect(self.clearQueue)
        buttonLayout.addWidget(self.buttonReset)

        mainLayout.addLayout(outputFolderROw)
        mainLayout.addWidget(self.pdfListWidget)
        mainLayout.addLayout(buttonLayout)
        self.setLayout(mainLayout)

    def deleteSelected(self):
        for item in self.pdfListWidget.selectedItems():
            self.pdfListWidget.takeItem(self.pdfListWidget.row(item))

    def addFolderPath(self):
        add_folder_path = QFileDialog.getExistingDirectory(self, 'addfolder',os.getcwd())
        return self.pdfListWidget.addItem(str(add_folder_path))
    
    def clearQueue(self):
        self.pdfListWidget.clear()
        self.outputFIle.setText('')

    def dialogMessage(self, message):
        dig = QMessageBox(self)
        dig.setWindowTitle('PDF Manager')
        dig.setIcon(QMessageBox.Information)
        dig.setText(message)
        dig.show()

    def _getSaveFilePath(self):
        file_save_path, _ = QFileDialog.getSaveFileName(self, 'Save PDF file', os.getcwd(), 'pdf file(*.pdf)')
        return file_save_path
    
    def populateFileName(self):
        path = self._getSaveFilePath()
        if path:
            self.outputFIle.setText(path)

    def mergeFile(self):
        if not self.outputFIle.text():
            self.populateFileName()
            return
        
        if self.pdfListWidget.count() > 0:
            pdfMerger = PdfMerger()

            try:
                for i in range(self.pdfListWidget.count()):
                    pdfMerger.append(self.pdfListWidget.item(i).text())

                pdfMerger.write(self.outputFIle.text())
                self.dialogMessage('pdf merge complete')

            except Exception as e:
                self.dialogMessage(e)
        else:
            self.dialogMessage('Queue is empty')

    def batch_merge(self):  #the error happen here when i click the button
        for root,dirs,files in os.walk(self.pdfListWidget): #dirs didn't get referenced for some reason
            merger = PdfMerger()    
        for filename in files:
            if filename.endswith(".pdf"):
                filepath = os.path.join(root, filename)
                merger.append(PdfReader(open(filepath, 'rb')))
        merger.write(os.path.join(self.pdfListWidget,os.path.basename(os.path.normpath(root))+'.pdf'))

app = QApplication(sys.argv)
app.setStyle('fusion')

pdfApp = PDFApp()
pdfApp.show()

sys.exit(app.exec_())
def batch_merge(self): 
        for root,dirs,files in os.walk(self.pdfListWidget.item().text()): #adding text for some but the path still not referenced
            merger = PdfMerger()    
        for filename in files:
            if filename.endswith(".pdf"):
                filepath = os.path.join(root, filename)
                merger.append(PdfReader(open(filepath, 'rb')))
        merger.write(os.path.join(self.pdfListWidget.item().text(),os.path.basename(os.path.normpath(root))+'.pdf'))

我试图添加self.pdfListWidget.item().text()使其像一个字符串,但得到另一个错误

File "c:\Users\fahmi\OneDrive\Desktop\pdf merge\pdf merge 5.py", line 245, in batch_merge
    for root,dirs,files in os.walk(self.pdfListWidget.item().text()): #dirs didn't get referenced for some reason
TypeError: item(self, row: int): not enough arguments

有没有办法将listwidget列表附加到os.walk方法中?

kqlmhetl

kqlmhetl1#

您提供的代码中似乎存在一些不一致之处。initUI方法定义了两次,第二次实现不包括您提到的PDF合并功能。
尽管如此,我想我仍然可以帮助你解决你遇到的错误。你提到你收到一个错误,说列表小部件不是一个字符串。从你提供的代码来看,这个错误可能与你如何处理PDF文件的文件路径有关。
ListWidget类的dropEvent方法中,使用self.addItems向列表小部件添加文件路径(pdfFiles)。但是,当您稍后尝试在mergeFile方法中合并PDF文件时,您将列表小部件视为字符串,这不是正确的类型。要合并PDF文件,您需要从列表小部件项中提取文件路径,并将其传递给PDF合并器。
下面是一个更新后的mergeFile方法,应该可以满足您的需求:

def mergeFile(self):
    merger = PdfMerger()

    # Get the file paths of the PDF files from the list widget
    pdfFiles = [self.pdfListWidget.item(i).text() for i in range(self.pdfListWidget.count())]

    # Merge the PDF files
    for pdfFile in pdfFiles:
        with open(pdfFile, 'rb') as f:
            merger.append(PdfReader(f))

    # Save the merged PDF to the output file
    outputFile = self.outputFIle.text()
    with open(outputFile, 'wb') as f:
        merger.write(f)
    
    # Reset the list widget and output field
    self.pdfListWidget.clear()
    self.outputFIle.clear()

在这个方法的更新版本中,我们首先通过迭代列表widget项目并对每个项目调用text()方法,从列表widget中提取PDF文件的文件路径。然后使用这些文件路径使用PyPDF2中的PdfMerger类合并PDF文件。
合并PDF文件后,我们将合并的PDF保存到输出字段中指定的输出文件中,最后,我们清除列表小部件和输出字段,以便为下一组PDF文件重置GUI。

trnvg8h3

trnvg8h32#

很抱歉,我误解了问题。发生错误的原因是您将QListWidgetItem对象传递给os.walk()函数,而不是其文本值。
修改
batch_merge()函数,获取pdfListWidget
中所有项目的文本,然后将其作为合并PDF文件的路径:

def batch_merge(self):
    for index in range(self.pdfListWidget.count()):
        path = self.pdfListWidget.item(index).text()
        merger = PdfMerger()    
        for root, dirs, files in os.walk(path):
            for filename in files:
                if filename.endswith(".pdf"):
                    filepath = os.path.join(root, filename)
                    merger.append(PdfReader(open(filepath, 'rb')))
            merger.write(os.path.join(path, os.path.basename(os.path.normpath(root)) + '.pdf'))

此代码将遍历pdfListWidget中的所有项目,并使用**text()**方法从每个项目中提取文本,然后将这些文本值中的每一个作为路径来合并相应文件夹中的PDF文件。
希望这能更好地回答你的问题。

相关问题