PyQt5 使用布局向小部件子类添加额外的小部件?

PyQt5 adding additional widgets to a widget subclass using layouts?

我正在尝试子类化 QListWidget 并在其上方添加一个搜索框。我知道我可以通过子类化 QWidget 并为其提供包含 QListWidgetQLineEdit 的布局来创建它,但我宁愿它是 QListWidget 的直接子类所以它可以很容易地替换我代码中现有的 QListWidgets 并保留所有可能被父小部件调用的继承方法。

这是我的尝试,但我不确定如何将 QListWidgetQLineEdit 一起放入布局中,layout.addWidget(self) 不起作用。

import re
from PyQt5 import QtCore, QtGui, QtWidgets


class SearchableListWidget(QtWidgets.QListWidget):
    def __init__(self, items, parent=None):
        super().__init__(parent=parent)

        self.initial_items = items
        self.set_items(items)

        self.search_box = QtWidgets.QLineEdit()
        self.search_box.textChanged.connect(self.filter)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.search_box)
        self.setLayout(layout)

    def filter(self):
        filtered_items = [item for item in self.initial_items
                          if re.search(self.search_box.text().lower(), item.lower())]

        self.set_items(filtered_items)

    def get_items(self):
        return [str(self.item(i).text()) for i in range(self.count())]

    def set_items(self, items):
        self.clear()
        for name in items:
            self.addItem(name)


if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)

    test = SearchableListWidget(['a', 'b', 'c'])
    test.show()

    sys.exit(app.exec_())

我得到的:

我想要的:

问题出在您的程序结构上:window 是 SearchableListWidget,它是一个 QListWidget,您通过布局在其中放置了 QLineEdit,但正确的做法是创建一个 class继承自 QWidget 之类的容器,并通过 QVBoxLayout 垂直放置 QLineEdit 和 QListWidget:

import re
from PyQt5 import QtCore, QtGui, QtWidgets


class SearchableWidget(QtWidgets.QWidget):
    def __init__(self, items, parent=None):
        super().__init__(parent)

        self.search_box = QtWidgets.QLineEdit()
        self.search_box.textChanged.connect(self.filter)

        self.list_widget = QtWidgets.QListWidget()

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.search_box)
        layout.addWidget(self.list_widget)

        self.initial_items = items
        self.set_items(items)

    def filter(self):
        filtered_items = [
            item
            for item in self.initial_items
            if re.search(self.search_box.text().lower(), item.lower())
        ]

        self.set_items(filtered_items)

    def get_items(self):
        return [
            str(self.list_widget.item(i).text())
            for i in range(self.list_widget.count())
        ]

    def set_items(self, items):
        self.list_widget.clear()
        for name in items:
            self.list_widget.addItem(name)


if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)

    test = SearchableWidget(["a", "b", "c"])
    test.show()

    sys.exit(app.exec_())