隐藏小部件后绘画被裁剪

时间:2020-04-25 09:36:56

标签: python pyqt qpainter qheaderview

我试图将QLineEdit添加到QHeaderView,以便可以从QSortFilterProxyModel过滤单词。

首先,标题可能只显示标题和搜索图标。 当用户单击图标时,QLineEdit将在右侧打开,覆盖搜索按钮,标题将移至标题的左侧。

随着editingFinished信号的发出,QLineEdit保存当前文本,paintSection在标题上绘制标题和QLineEdit,就像委托一样。 如果QLineEdit为空,则搜索结束,paintSection只是返回到第一个布局,只有标题带有搜索图标。

但是,在我的代码中,随着搜索结束,paintSection只会刷新被QLineEdit覆盖的部分,而未被其覆盖的部分将保持不变,直到某种事件触发重新绘制为止。

Behavior

我对Qt的绘画系统不太满意,所以我对此感到非常沮丧。

这是我当前的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

1 个答案:

答案 0 :(得分:0)

好吧,我已经完成了一些事件过滤和处理工作,发现调用editingFinished时,仅layoutRequest事件会由于隐藏编辑器小部件而引发,并且该事件当然没有重画背景。

因此,我尝试在repaint函数的末尾添加updateeditingFinished,但是它们根本没有调用任何事件。当我叫他们 before 小部件被隐藏时,现在它们触发了paintEvent,但仅触发了放置我的小部件的区域。

在那之后,我在Qt for Python文档中找到了一个插槽updateSection,它确实起作用了!我不确定它是否可以在C ++ Qt上使用,因为我在C ++ Qt文档上找不到相同的插槽。

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