0

我正在尝试将 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
4

1 回答 1

0

好的,我已经做了一些事件过滤和一些事情,发现当editingFinished被调用时,由于隐藏了编辑器小部件,只有layoutRequest事件引发,而且这个事件当然没有重新绘制背景。

所以我尝试在函数末尾添加repaint或,但他们根本没有调用任何事件。当我在小部件隐藏之前调用它们时,现在它们触发了,但仅触发了放置我的小部件的区域。updateeditingFinishedpaintEvent

之后,我updateSection在 Qt for Python 文档中找到了一个插槽,它确实有效!我不确定它是否适用于 C++ Qt,因为我在 C++ Qt 文档中找不到相同的插槽。

我仍然很好奇为什么当我使用“repaint”或“update”时标题没有更新,但这是另一个问题。

于 2020-05-03T13:13:36.980 回答