Почему QListView дает мне NoneType при попытке получить текст? - PullRequest
3 голосов
/ 16 января 2020

Я пишу простой поисковик файлов в PyQt5 (полный код здесь).

# -*- coding: utf-8 -*-

import sys, os, platform, fnmatch
from PyQt5 import QtCore, QtGui, QtWidgets

sep = os.sep
Ot = platform.system()
file_name = os.path.basename(__file__)
file_path = __file__.replace(file_name, '')

def find(ext, path):
    result = []
    for root, dirs, files in os.walk(path):
        for name in files:
            if fnmatch.fnmatch(name, ext):
                result.append(os.path.join(root, name))
    _ = dirs # For PyLint
    return result

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(804, 554)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("C:/Users/Luger/Pictures/ico/search.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.folderButton = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(9)
        self.folderButton.setFont(font)
        self.folderButton.setObjectName("folderButton")
        self.horizontalLayout.addWidget(self.folderButton)
        self.extensionLineEdit = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(9)
        self.extensionLineEdit.setFont(font)
        self.extensionLineEdit.setMaxLength(25)
        self.extensionLineEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.extensionLineEdit.setObjectName("extensionLineEdit")
        self.horizontalLayout.addWidget(self.extensionLineEdit)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.searchButton = QtWidgets.QPushButton(self.centralwidget)
        self.searchButton.setObjectName("searchButton")
        self.verticalLayout.addWidget(self.searchButton)
        self.verticalLayout_2.addLayout(self.verticalLayout)
        self.listView = QtWidgets.QListView(self.centralwidget)
        self.listView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listView.setIconSize(QtCore.QSize(16, 16))
        self.listView.setObjectName("listView")
        self.entry = QtGui.QStandardItemModel()
        self.listView.setModel(self.entry)
        self.verticalLayout_2.addWidget(self.listView)
        self.horizontalLayout_2.addLayout(self.verticalLayout_2)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 804, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.folderButton.clicked.connect(self.fileChooserFunct)
        self.searchButton.clicked.connect(self.searchButtonFunct)
        self.listView.clicked[QtCore.QModelIndex].connect(self.on_clicked)

    def fileChooserFunct(self):
        _translate = QtCore.QCoreApplication.translate
        self.dir_to_scan = QtWidgets.QFileDialog.getExistingDirectory(None, 'Select A folder:', f'{file_path[0]}:{sep}', QtWidgets.QFileDialog.ShowDirsOnly)
        self.folderButton.setText(_translate("MainWindow", f" Selected: {self.dir_to_scan} "))
        self.folderButton.adjustSize()
        if Ot == 'Windows': self.dir_to_scan = self.dir_to_scan.replace('/', '\\')

    def searchButtonFunct(self):
        _translate = QtCore.QCoreApplication.translate
        self.searchButton.setText(_translate("MainWindow", "Searching, please wait..."))
        MainWindow.setWindowTitle(_translate("MainWindow", "File Searcher - Searching"))
        self.searchButton.adjustSize()
        self.userExtension = self.extensionLineEdit.text()
        result = find(f'*.{self.userExtension}', self.dir_to_scan)

        model = QtGui.QStandardItemModel()
        self.listView.setModel(model)

        for i in result:
            item = QtGui.QStandardItem(i)
            model.appendRow(item)

        self.searchButton.setText(_translate("MainWindow", "Search"))
        MainWindow.setWindowTitle(_translate("MainWindow", "File Searcher"))
        self.searchButton.adjustSize()

    def on_clicked(self, index):
        item = self.entry.itemFromIndex(index)
        print(f"itemText='{item.text()}'")


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "File Searcher"))
        self.folderButton.setText(_translate("MainWindow", " Select a folder "))
        self.extensionLineEdit.setPlaceholderText(_translate("MainWindow", "Extension of the file"))
        self.searchButton.setText(_translate("MainWindow", "Search"))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('Fusion')
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Основываясь на ответе пользователя, я добавил это MRE (надеюсь, это правильно)

        self.listView = QtWidgets.QListView(self.centralwidget) #create the widget
        self.listView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) #paths cannot be modified by the user
        self.listView.setObjectName("listView") # Set his name
        self.entry = QtGui.QStandardItemModel() #Those two I don't really know what are for
        self.listView.setModel(self.entry)

        self.listView.clicked[QtCore.QModelIndex].connect(self.on_clicked) #User clicked something in QListView, calling on_clicked


    def on_clicked(self, index):
        item = self.entry.itemFromIndex(index)
        print(f"itemText='{item.text()}'") #Error is given here

Я использовал QtDesigner и преобразовал файл пользовательского интерфейса, используя pyuic5.exe, немного изменил, и теперь я застрял при извлечении выбранного пользователем объекта в QListView.

Я использовал немного кода S.Nick in этот ответ . Даже используя его код и используя те же имена переменных, когда я щелкаю по объекту, я получаю AttributeError: 'NoneType' object has no attribute 'text' (его код работал без проблем).

Ошибка дается здесь

    def on_clicked(self, index):
        item = self.entry.itemFromIndex(index)
        print(f"itemText='{item.text()}'")

Я начал поиск решения 2 дня go, и я просмотрел большинство ответов, сайтов, примеров, видеороликов stackoverflow (даже 1 час двух парней, говорящих по-русски), но все же я заблокирован здесь.
Кто-нибудь знает как это исправить? Спасибо

1 Ответ

3 голосов
/ 16 января 2020

Проблема заключается в том, что в методе searchButtonFunct вы создаете новую модель для QListView, чтобы QModelIndex принадлежал этой новой модели, поэтому использование self.entry.itemFromIndex() с QModelIndex, который не принадлежит этой модели, вернет None.

Решение состоит в том, чтобы использовать ту же модель:

def searchButtonFunct(self):
    self.entry.clear()
    _translate = QtCore.QCoreApplication.translate
    self.searchButton.setText(_translate("MainWindow", "Searching, please wait..."))
    MainWindow.setWindowTitle(_translate("MainWindow", "File Searcher - Searching"))
    self.searchButton.adjustSize()
    self.userExtension = self.extensionLineEdit.text()
    result = find(f"*.{self.userExtension}", self.dir_to_scan)

    for i in result:
        item = QtGui.QStandardItem(i)
        self.entry.appendRow(item)

    self.searchButton.setText(_translate("MainWindow", "Search"))
    MainWindow.setWindowTitle(_translate("MainWindow", "File Searcher"))
    self.searchButton.adjustSize()
...