1

我想在 PyQt5 中创建一个 QHeaderView,就像在这个项目中使用的一样(DB Browser for SQLite)。问题是我不懂 C++,也不明白类和小部件是如何从 GitHub 上的源代码创建的。有人如何在python中模拟这个过滤器头吗?

https://github.com/sqlitebrowser/sqlitebrowser/blob/master/src/FilterTableHeader.h

4

1 回答 1

1

这是该方法的一个非常基本的实现。

这个概念是为标题提供正确的 sizeHint(标题的默认提示加上行编辑的高度)并用于setViewportMargins确保标题具有文本字段使用的底部边距。

class Header(QtWidgets.QHeaderView):
    filterChanged = QtCore.pyqtSignal(int, str)
    fieldsVisible = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields = []
        self.sectionCountChanged.connect(self.generateFields)
        self.sectionResized.connect(self.updateFields)
        self.parent().horizontalScrollBar().valueChanged.connect(self.updateFields)
        self.parent().verticalScrollBar().valueChanged.connect(self.updateFields)

    def setFieldsVisible(self, visible):
        if visible == self.fieldsVisible:
            return
        self.fieldsVisible = visible
        self.generateFields()

    def generateFields(self):
        while self.fields:
            self.fields.pop().deleteLater()
        if self.fieldsVisible:
            for s in range(self.count()):
                edit = QtWidgets.QLineEdit(self)
                edit.show()
                self.fields.append(edit)
                edit.textChanged.connect(lambda text, s=s: self.filterChanged.emit(s, text))
            self.updateFields()
        self.updateGeometries()

    def updateFields(self):
        offset = self.offset()
        y = QtWidgets.QHeaderView.sizeHint(self).height()
        for section, field in enumerate(self.fields):
            field.move(self.sectionPosition(section) - offset, y)
            field.resize(self.sectionSize(section), field.sizeHint().height())

    def updateGeometries(self):
        if self.fields:
            self.setViewportMargins(0, 0, 0, self.fields[0].sizeHint().height())
        else:
            self.setViewportMargins(0, 0, 0, 0)
        super().updateGeometries()
        # ensure that the parent view updates correctly
        self.parent().updateGeometries()
        self.updateFields()

    def sizeHint(self):
        hint = super().sizeHint()
        if self.fields:
            hint.setHeight(hint.height() + self.fields[0].sizeHint().height())
        return hint


class SearchTable(QtWidgets.QTableView):
    def __init__(self):
        super().__init__()
        model = QtGui.QStandardItemModel()
        for row in range(8):
            model.appendRow([QtGui.QStandardItem('Item {} {}'.format(row, i)) for i in range(8)])
        self.setModel(model)
        self.setHorizontalHeader(Header(QtCore.Qt.Horizontal, self))

注意这个例子没有考虑移动部分的可能性,如果你想实现一个多列过滤器,你需要一个 QSortFilterProxyModel 的子类(例如,这里提供的那个)。我提供了一个基本信号 ( filterChanged),它将返回该部分并更改文本。

于 2020-06-02T13:12:32.147 回答