我正在尝试将 QLineEdit 添加到 QHeaderView 以便我可以过滤来自 QSortFilterProxyModel 的单词。
起初,标题可能只显示标题和搜索图标。当用户单击该图标时,QLineEdit 在右侧打开,覆盖搜索按钮,并且标题移动到标题的左侧。
当editingFinished 信号发出时,QLineEdit 保存当前文本,而paintSection 在标题上绘制标题和QLineEdit,就像委托一样。如果 QLineEdit 为空,则搜索结束并且paintSection 只是返回到第一个布局,只有带有搜索图标的标题。
但是,在我的代码中,当搜索结束时,paintSection 仅刷新被 QLineEdit 覆盖的部分,而未被它覆盖的部分保持不变,直到某种事件触发重新绘制。
我对Qt的painter系统不太友好,所以我对这个问题感到非常沮丧。
这是我当前的 HeaderView 代码。不包括负责打开 QLineEdit 的函数。HeaderData 只是一个包含 Header 信息的简单类。
class HeaderView(QHeaderView):
def __init__(self, orientation=Qt.Horizontal):
super().__init__(orientation)
self.setSectionsMovable(True)
self.setSectionsClickable(True)
self.editIndex = -1
self.headers = []
self.searchImage = QImage('search.png')
h = HeaderData()
self.headers.append(h)
self.line = QLineEdit(self.viewport())
self.line.hide()
self.line.editingFinished.connect(self.editingFinished)
self.line.textChanged.connect(self.textChanged)
def paintSection(self, painter, rect, logicalIndex):
if self.headers[logicalIndex].search is True: # currently searching
# Left half is filled with title
text_rect = QRect(rect.x(), rect.y(), rect.width()//2, rect.height())
painter.drawText(text_rect, Qt.AlignCenter, self.model().headerData(logicalIndex, self.orientation(), Qt.DisplayRole))
# Right half is area for QLineEdit
rel_pos = painter.deviceTransform().map(QPoint(rect.x(), rect.y()))
line_rect = QRect(rect.width() // 2, 0, rect.width() // 2, rect.height())
line_pos = rel_pos + line_rect.topLeft()
device = painter.device()
w = QLineEdit()
w.resize(line_rect.size())
w.setText(self.headers[logicalIndex].line_text)
w.render(device, line_pos, QRegion(0, 0, w.width(), w.height()), QWidget.RenderFlag.DrawChildren)
self.headers[logicalIndex].line_rect = line_rect
else: # not searching
painter.drawText(rect, Qt.AlignCenter, self.model().headerData(logicalIndex, self.orientation(), Qt.DisplayRole))
point = rect.topLeft()
offset = QPoint(rect.width() - rect.height(), rect.height()//4)
icon_size = QSize(rect.height()//2, rect.height()//2))
painter.drawImage(point + offset, self.searchImage.scaled(icon_size)
self.headers[logicalIndex].search_rect = QRect(offset, icon_size)
def openEditor(self, index):
self.editIndex = index
line_rect = self.headers[index].line_rect.translated(self.sectionViewportPosition(index), 0)
self.line.setGeometry(line_rect)
self.line.setText(self.headers[index].line_text)
self.line.setVisible(True)
def textChanged(self, text):
self.headers[self.editIndex].line_text = text
def editingFinished(self):
if self.line.text() == '':
self.headers[self.editIndex].search = False
self.line.hide()
self.headers[self.editIndex].line_text = self.line.text()
self.editIndex = -1