如何在存储在一个大列表中的所有列表中搜索匹配项

2024-06-10 09:01:15 发布

您现在位置:Python中文网/ 问答频道 /正文

这个题目很难。我有两个主要问题。首先,我想自我。Nnum等于我创建的“页面选择器”函数中的“Selected\Nnum\u and\u Anum”,这样我就可以继续点击页面了。其次,我需要创建一个搜索函数,读取“Namepages2”列表来搜索匹配项。问题是“Namepages2”是一个列表,其中充满了其他列表(其中的列表数量可以/将发生变化)。我不确定如何找到匹配项,我希望函数为“”输出一个值自我。Nnum当我键入所需的项目(从原始的“名称”列表)时,我可以在“页码”行编辑中显示它。你知道吗

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QPushButton, QLineEdit, QHBoxLayout, QLabel, QFrame, QVBoxLayout, QGridLayout, QWidget

Names = ['Bob','Randy','Dakota','Steven','Clarke','Niomi','David','Nathan','James','Joe','Jacob','Jonah','Jerome','Jack','Jeremy','Jackson','Jamie']
Ages = ['51','32','22','19','40','27','19','45','1','2','3','4','5','6','7','8','9']

class MyWindow(QtWidgets.QMainWindow):                        # Window setup
    def __init__(self):                                       # Window setup
        super(MyWindow, self).__init__()                      # Window setup
        centralWidget = QWidget()                             # Window setup
        self.setCentralWidget(centralWidget)                  # Window setup
        self.setWindowTitle("ASSET")                          # Window setup
        self.OpenButton = QPushButton('Open',self)            # Creates the open button
        self.OpenButton.clicked.connect(self.Open)            # Links the open button to the "open" function
        self.SaveButton = QPushButton('Save',self)            # Creates the save button
        self.SearchBar = QLineEdit('Search',self)             # Creates the SearchBar LineEdit
        self.SearchBar.textChanged.connect(self.Search)
        self.PreviousButton = QPushButton('Previous',self)    # Creates the previous button
        self.PreviousButton.clicked.connect(lambda: self.PreviousPage(self.MainFrame2.layout())) # Links the previous button to the "PreviousPage" function
        self.NextButton = QPushButton('Next',self)            # Creates the next button
        self.NextButton.clicked.connect(lambda: self.NextPage(self.MainFrame2.layout()))         # Links the next button to the "NextPage" function
        self.Page_Number = QLineEdit('Page Number',self)      # Creates the Page_Number LineEdit
        self.Page_Number.returnPressed.connect(lambda: self.Page_Selector(self.MainFrame2.layout()))
        self.MainFrame = QFrame(self)                         # Creates a frame
        self.MainFrame2 = QFrame(self)                        # Creates a frame
        self.MainFrame3 = QFrame(self)                        # Creates a frame
        self.MainHlayout = QHBoxLayout(self.MainFrame)        # Adds a Horizontal Layout
        self.MainHlayout2 = QHBoxLayout(self.MainFrame2)      # Adds a Horizontal Layout
        self.MainHlayout3 = QHBoxLayout(self.MainFrame3)      # Adds a Horizontal Layout

        self.Glayout = QGridLayout(centralWidget)             # Adds a grid layout to the main window
        self.Glayout.addWidget(self.MainFrame)                # Adds a frame to the main window's layout (it will be the top frame since it was added first)
        self.Glayout.addWidget(self.MainFrame2)               # Adds a frame to the main window's layout (this will be the middle frame)
        self.Glayout.addWidget(self.MainFrame3)               # Adds a frame to the main window's layout (this will be the bottom frame)
        self.MainHlayout.addWidget(self.OpenButton)           # Adds the open button to the top frame's layout
        self.MainHlayout.addWidget(self.SearchBar)            # Adds the search bar to the top frame's layout
        self.MainHlayout.addWidget(self.SaveButton)           # Adds the save button to the top frame's layout
        self.MainHlayout3.addWidget(self.PreviousButton)      # Adds the previous button to the bottom frame's layout
        self.MainHlayout3.addWidget(self.Page_Number)         # Adds the Page_Number LineEdit to the bottom frame's layout
        self.MainHlayout3.addWidget(self.NextButton)          # Adds the next button to the bottom frame's layout

        self.SubFrame = QFrame(self)                      # Creates a new frame
        self.SubVlayout = QVBoxLayout(self.SubFrame)      # Adds a vertical layout to the new frame
        self.MainHlayout2.addWidget(self.SubFrame)        # Adds the new frame to the middle frame
        self.Has_Been_Pressed = False                     # Sets the Has_Been_Pressed variable to False (will explain later)


    def Open(self):                                                     # This function is called when the open button is clicked
        self.Has_Been_Pressed = True                                    # This sets the Has_Been_Pressed variable to True
        self.Nnum = 0                                                   # Sets the Nnum variable to 0
        self.Namepages = []                                             # Creates an empty list
        BasicCounter1 = 0                                               # Sets the BasicCounter1 variable to 0
        BasicCounter2 = 1                                               # Sets the BasicCounter2 variable to 1
        while (8 * BasicCounter1) < len(Names):                         # Creates a while loop with the condition: while 8 * BasicCounter is less than the length of the list "Names"
            yN = Names[0 + (8 * BasicCounter1):8 * BasicCounter2]       # The new variable "yN" equals the list 'Names" from: 0 + 8*BasicCounter to 8*BasicCounter2
            self.Namepages.insert(0, yN)                                # Inserts "yN" to the blank list "NamePages"
            BasicCounter1 += 1                                          # Adds 1 to BasicCounter1
            BasicCounter2 += 1                                          # Adds 1 to BasicCounter2
        self.Namepages2 = list(reversed(self.Namepages))                # Reverses the list order of "NamePages"
        self.Namepage = self.Namepages2[self.Nnum]                      # Sets the specified numbered item (based on value of "Nnum") of list "NamePages" to "NamePage"

        self.Anum = 0                                                   # Exact Same as the last While Loop, but using a different list "Ages"
        self.Agepages = []
        BasicCounter3 = 0
        BasicCounter4 = 1
        while (8 * BasicCounter3) < len(Ages):
            yA = Ages[0 + (8 * BasicCounter3):8 * BasicCounter4]
            self.Agepages.insert(0, yA)
            BasicCounter3 += 1
            BasicCounter4 += 1
        self.Agepages2 = list(reversed(self.Agepages))
        self.Agepage = self.Agepages2[self.Anum]

        self.i = 0                                                                    # Sets the variable "i" to 0
        self.Widget_Counter = 0                                                       # Sets the variable "Widget_Counter" to 0
        while self.i < len(self.Namepage):                                            # Creates a while loop with the condition: while the variable "i" is less than the list "Namepage"
            if self.Widget_Counter <= 3:                                              # if statement that reads: if the variable "Widget_Counter" is less than or equal to 3
                    self.SubVlayout.addWidget(QLabel(self.Namepage[self.i], self))    # Adds a new label (that reads a specified item from "Namepage" depending on the value of "i") to the vertical layout in the subframe that was added to the middle frame
                    self.SubVlayout.addWidget(QLineEdit(self.Agepage[self.i], self))  # Does the same as above, but instead creates a LineEdit and fills it with a specified value from "Agepage"
                    self.i += 1                                                       # Adds 1 to "i"
                    self.Widget_Counter += 1                                          # Adds 1 to "Widget_Counter"
            elif self.Widget_Counter > 3:                                             # The other condition/path reads: if the variable "Widget_Counter" is greater than 3
                    self.SubFrame = QFrame(self)                                      # Creates a new frame. Since it shares the same name as the previous "SubFrame", the code will now refer to THIS one instead
                    self.SubVlayout = QVBoxLayout(self.SubFrame)                      # Adds a vertical layout to the new frame
                    self.MainHlayout2.addWidget(self.SubFrame)                        # Adds the new frame to the middle frame (which has a horizontal layout, therefore is to the right of the previous "SubFrame")
                    self.Widget_Counter = 0                                           # Sets "Widget_Counter" to 0

        # print(len(self.Namepages2))
        # print(self.Nnum)
        # print(self.Namepages2[1])

    def NextPage(self, layout):                                      # This function is called when the next button is clicked
        if self.Has_Been_Pressed:                                    # This if statement reads: if "Has_Been_Pressed" is True   (basically everything under the if statement will only run if the open button is pressed, bc that means "Has_Been_Pressed" = True)
            if self.Nnum < len(self.Namepages2) -1:                  # If statement that reads: If Nnum is less than the length of Namepages2 minus 1. This stops the loop from running when you reach the end of the list "Namepages"
                self.Nnum += 1                                       # Adds 1 to "Nnum"
                self.Anum += 1                                       # Adds 1 to "Anum"
                if layout is not None:                               # This if statement clears all widgets in the horizontal layout in "MainFrame2" (aka the middle frame)
                    while layout.count():
                        item = layout.takeAt(0)
                        widget = item.widget()
                        if widget is not None:
                            widget.deleteLater()
                        else:
                            self.clearLayout(item.layout())

                self.SubFrame = QFrame(self)                        # Creates another new frame called "SubFrame"
                self.SubVlayout = QVBoxLayout(self.SubFrame)        # Adds a vertical layout to the new frame
                self.MainHlayout2.addWidget(self.SubFrame)          # Adds the new frame into the recently cleared horizontal layout in "MainFrame2" (aka the middle frame)

                self.Namepage = self.Namepages2[self.Nnum]          # Changes Namepage to the next list in Namepages2 (this happens bc Nnum increases by one when the button is clicked)
                self.Agepage = self.Agepages2[self.Anum]            # Same idea
                self.i = 0                                          # sets "i" back to zero
                self.Widget_Counter = 0                             # sets 'Widget_Counter" back to zero
                while self.i < len(self.Namepage):                  # Same loop as before, but Namepage is different so it will display new data
                    if self.Widget_Counter <= 3:
                        self.SubVlayout.addWidget(QLabel(self.Namepage[self.i], self))
                        self.SubVlayout.addWidget(QLineEdit(self.Agepage[self.i], self))
                        self.i += 1
                        self.Widget_Counter += 1
                    elif self.Widget_Counter > 3:
                        self.SubFrame = QFrame(self)
                        self.SubVlayout = QVBoxLayout(self.SubFrame)
                        self.MainHlayout2.addWidget(self.SubFrame)
                        self.Widget_Counter = 0
                self.Page_Number.setText(str(self.Nnum + 1))
            else:
                pass
        else:
            pass

    def PreviousPage(self, layout):     # Same as "Next Button" but you're subtracting one from Nnum and Anum. The new Nnum limit is now zero.
        if self.Has_Been_Pressed:
            if self.Nnum >= 1:
                self.Nnum -= 1
                self.Anum -= 1
                if layout is not None:
                    while layout.count():
                        item = layout.takeAt(0)
                        widget = item.widget()
                        if widget is not None:
                            widget.deleteLater()
                        else:
                            self.clearLayout(item.layout())

                self.SubFrame = QFrame(self)
                self.SubVlayout = QVBoxLayout(self.SubFrame)
                self.MainHlayout2.addWidget(self.SubFrame)

                self.Namepage = self.Namepages2[self.Nnum]
                self.Agepage = self.Agepages2[self.Anum]
                self.i = 0
                self.Widget_Counter = 0
                while self.i < len(self.Namepage):
                    if self.Widget_Counter <= 3:
                        self.SubVlayout.addWidget(QLabel(self.Namepage[self.i], self))
                        self.SubVlayout.addWidget(QLineEdit(self.Agepage[self.i], self))
                        self.i += 1
                        self.Widget_Counter += 1
                    elif self.Widget_Counter > 3:
                        self.SubFrame = QFrame(self)
                        self.SubVlayout = QVBoxLayout(self.SubFrame)
                        self.MainHlayout2.addWidget(self.SubFrame)
                        self.Widget_Counter = 0
                self.Page_Number.setText(str(self.Nnum + 1))
            elif self.Nnum < 0:
                self.Nnum += 1
        else:
            pass


    def Page_Selector(self,layout):
        if self.Has_Been_Pressed:
                Inputted_Value = int(self.Page_Number.text())
                Selected_Nnum_and_Anum = Inputted_Value - 1
                if 0 <= Selected_Nnum_and_Anum < 3:
                    if layout is not None:
                        while layout.count():
                            item = layout.takeAt(0)
                            widget = item.widget()
                            if widget is not None:
                                widget.deleteLater()
                            else:
                                self.clearLayout(item.layout())
                    self.SubFrame = QFrame(self)
                    self.SubVlayout = QVBoxLayout(self.SubFrame)
                    self.MainHlayout2.addWidget(self.SubFrame)

                    Selected_Namepage = self.Namepages2[Selected_Nnum_and_Anum]
                    Selected_Agepage = self.Agepages2[Selected_Nnum_and_Anum]
                    self.i = 0
                    self.Widget_Counter = 0
                    while self.i < len(Selected_Namepage):
                        if self.Widget_Counter <= 3:
                            self.SubVlayout.addWidget(QLabel(Selected_Namepage[self.i], self))
                            self.SubVlayout.addWidget(QLineEdit(Selected_Agepage[self.i], self))
                            self.i += 1
                            self.Widget_Counter += 1
                        elif self.Widget_Counter > 3:
                            self.SubFrame = QFrame(self)
                            self.SubVlayout = QVBoxLayout(self.SubFrame)
                            self.MainHlayout2.addWidget(self.SubFrame)
                            self.Widget_Counter = 0

                    # self.Nnum = Selected_Nnum_and_Anum     # This will not work!
                else:
                    pass
        else:
            pass


    def Search(self, text):    # I have no idea where to start here!
        pass


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

Tags: thetoselfifiscounterwidgetframe
1条回答
网友
1楼 · 发布于 2024-06-10 09:01:15

OP代码太长、太乱、太混乱,无法作为解决方案的基础,所以请花时间创建自己的实现。你知道吗

在本例中,我将信息集中在模型中,通过QDataWidgetMapper将小部件关联起来,从而允许GUI和模型共享相同的更新信息。另一个变化是使用适当的小部件,例如,如果您的数据是数字,那么使用QSpinBox比使用QLineEdit更好。此外,如果页面上的项目数少于预期,则小部件将被隐藏。你知道吗

最后,使用模型的findItems()实现搜索。你知道吗

以上所有内容将在以下部分中实现:

import math
from PyQt5 import QtCore, QtGui, QtWidgets


class PageWidget(QtWidgets.QWidget):
    openClicked = QtCore.pyqtSignal()
    saveClicked = QtCore.pyqtSignal()

    def __init__(self, items_per_page=8, parent=None):
        super(PageWidget, self).__init__(parent)

        self.items_model = QtGui.QStandardItemModel(0, 2, self)

        self._current_page = -1

        self.open_button = QtWidgets.QPushButton("&Open")
        self.save_button = QtWidgets.QPushButton("&Save")
        self.search_lineedit = QtWidgets.QLineEdit(placeholderText="Search")

        self.previous_button = QtWidgets.QPushButton("&Previous")
        self.next_button = QtWidgets.QPushButton("&Next")
        self.page_spinbox = QtWidgets.QSpinBox(maximum=0)

        self.open_button.clicked.connect(self.openClicked)
        self.save_button.clicked.connect(self.saveClicked)
        self.search_lineedit.textChanged.connect(self.search)
        self.page_spinbox.valueChanged.connect(self.set_current_page)

        self.previous_button.clicked.connect(self.previous_page)
        self.next_button.clicked.connect(self.next_page)

        completer = QtWidgets.QCompleter(self)
        completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion)
        completer.setModel(self.items_model)
        self.search_lineedit.setCompleter(completer)

        top_widget = QtWidgets.QWidget()
        h_top_lay = QtWidgets.QHBoxLayout(top_widget)
        h_top_lay.setContentsMargins(0, 0, 0, 0)
        h_top_lay.addWidget(self.open_button)
        h_top_lay.addWidget(self.search_lineedit)
        h_top_lay.addWidget(self.save_button)

        bottom_widget = QtWidgets.QWidget()
        h_bottom_lay = QtWidgets.QHBoxLayout(bottom_widget)
        h_bottom_lay.setContentsMargins(0, 0, 0, 0)
        h_bottom_lay.addWidget(self.previous_button)
        h_bottom_lay.addWidget(QtWidgets.QLabel("Page Number:"), 0)
        h_bottom_lay.addWidget(self.page_spinbox, 1)
        h_bottom_lay.addWidget(self.next_button)

        self._mapper_widgets = []
        items_widget = QtWidgets.QWidget()
        items_grid_layout = QtWidgets.QGridLayout(items_widget)
        items_grid_layout.setContentsMargins(0, 0, 0, 0)

        for i in range(8):
            name_label = QtWidgets.QLabel()
            age_spinbox = QtWidgets.QSpinBox()

            widget = QtWidgets.QWidget()
            lay = QtWidgets.QVBoxLayout(widget)
            lay.setContentsMargins(0, 0, 0, 0)
            lay.addWidget(name_label)
            lay.addWidget(age_spinbox)

            items_grid_layout.addWidget(widget, i // 2, i % 2)
            mapper = QtWidgets.QDataWidgetMapper(self)
            mapper.setModel(self.items_model)

            mapper.addMapping(name_label, 0, b"text")
            mapper.addMapping(age_spinbox, 1, b"value")

            self._mapper_widgets.append((widget, mapper))

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(top_widget, alignment=QtCore.Qt.AlignTop)
        lay.addWidget(items_widget, stretch=1, alignment=QtCore.Qt.AlignTop)
        lay.addWidget(bottom_widget, alignment=QtCore.Qt.AlignBottom)

        self._update_page(0)

    def set_data(self, data):
        self.items_model.clear()
        for values in data:
            items = []
            for value in values:
                item = QtGui.QStandardItem()
                item.setData(value, QtCore.Qt.DisplayRole)
                items.append(item)
            self.items_model.appendRow(items)
        self.current_page = 0
        self.page_spinbox.setMaximum(max(0, self.number_of_pages - 1))

    @property
    def number_of_pages(self):
        return math.ceil(self.items_model.rowCount() / len(self._mapper_widgets))

    def is_page_valid(self, page):
        return 0 <= page < self.number_of_pages

    def get_current_page(self):
        return self._current_page

    @QtCore.pyqtSlot(int)
    def set_current_page(self, page):
        if self.is_page_valid(page):
            self._update_page(page)
            self._current_page = page
            self.page_spinbox.setValue(page)

    current_page = QtCore.pyqtProperty(
        int, fget=get_current_page, fset=set_current_page
    )

    def next_page(self):
        self.current_page += 1

    def previous_page(self):
        self.current_page -= 1

    def _update_page(self, page):
        items_per_page = len(self._mapper_widgets)
        start_index = page * items_per_page
        end_index = min((page + 1) * items_per_page, self.items_model.rowCount())
        indexes = list(range(start_index, end_index))
        for i, (widget, mapper) in enumerate(self._mapper_widgets):
            if i < len(indexes):
                widget.show()
                mapper.setCurrentIndex(indexes[i])
            else:
                widget.hide()

        self.previous_button.setEnabled(page > 0)
        self.next_button.setEnabled(page < (self.number_of_pages - 1))

    @QtCore.pyqtSlot(str)
    def search(self, text):
        match_items = self.items_model.findItems(
            text, flags=QtCore.Qt.MatchStartsWith, column=0
        )
        if match_items:
            first_match_item, *_ = match_items

            name = first_match_item.data(QtCore.Qt.DisplayRole)
            print(name)

            row = first_match_item.row()
            page = row // len(self._mapper_widgets)
            self.current_page = page

    def to_list(self):
        data = []
        for i in range(self.items_model.rowCount()):
            name = self.items_model.item(i, 0).data(QtCore.Qt.DisplayRole)
            age = self.items_model.item(i, 1).data(QtCore.Qt.DisplayRole)
            data.append((name, age))
        return data


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.page_widget = PageWidget()
        self.page_widget.openClicked.connect(self.on_open_clicked)
        self.page_widget.saveClicked.connect(self.on_save_clicked)

        self.setCentralWidget(self.page_widget)

        self.resize(320, 360)

    @QtCore.pyqtSlot()
    def on_open_clicked(self):
        items = [
            ("Bob", 51),
            ("Randy", 32),
            ("Dakota", 22),
            ("Steven", 19),
            ("Clarke", 40),
            ("Niomi", 27),
            ("David", 19),
            ("Nathan", 45),
            ("James", 1),
            ("Joe", 2),
            ("Jacob", 3),
            ("Jonah", 4),
            ("Jerome", 5),
            ("Jack", 6),
            ("Jamie", 7),
            ("Jackson", 8),
            ("Jamie", 9),
        ]
        self.page_widget.set_data(items)

    @QtCore.pyqtSlot()
    def on_save_clicked(self):
        items = self.page_widget.to_list()
        print(items)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

相关问题 更多 >