在 PyQt5 中创建一个 DB Browser 风格的 QHeaderview
Create a DB Browser style QHeaderview in PyQt5
我想在 PyQt5 中创建一个 QHeaderView,就像在这个项目中使用的那样(DB Browser for SQLite)。问题是我不懂 C++,也不明白 类 和小部件是如何从 GitHub 上的源代码创建的。有人如何在 python 中模拟此过滤器 header 吗?
https://github.com/sqlitebrowser/sqlitebrowser/blob/master/src/FilterTableHeader.h
这是该方法的一个非常基本的实现。
概念是为页眉提供一个正确的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
),它将 return 部分和文本更改。
我想在 PyQt5 中创建一个 QHeaderView,就像在这个项目中使用的那样(DB Browser for SQLite)。问题是我不懂 C++,也不明白 类 和小部件是如何从 GitHub 上的源代码创建的。有人如何在 python 中模拟此过滤器 header 吗?
https://github.com/sqlitebrowser/sqlitebrowser/blob/master/src/FilterTableHeader.h
这是该方法的一个非常基本的实现。
概念是为页眉提供一个正确的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
),它将 return 部分和文本更改。