Картина после сокрытия виджета обрезается - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь добавить QLineEdit в QHeaderView, чтобы я мог фильтровать слова из QSortFilterProxyModel.

Сначала в заголовке могут отображаться только заголовок и значок поиска. Когда пользователь щелкает значок, QLineEdit открывается с правой стороны, закрывая кнопку поиска, а заголовок перемещается в левую часть заголовка.

По мере подачи сигнала editFinished 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 голосов
/ 03 мая 2020

Хорошо, я выполнил некоторую фильтрацию событий и прочее и обнаружил, что при вызове editingFinished возникает только событие layoutRequest из-за скрытия виджета редактора, и это событие определенно не перерисовывает фон.

Поэтому я попытался добавить repaint или update в конце функции editingFinished, но они вообще не вызывали никаких событий. Когда я вызывал их до того, как виджет стал скрытым, теперь они вызывали paintEvent, но только область, в которой был размещен мой виджет.

После этого я нашел слот updateSection в Qt для Python документации, и это сработало! Я не уверен, будет ли он работать на C ++ Qt, потому что я не смог найти тот же слот в документации на C ++ Qt.

Мне все еще интересно, почему заголовок не обновлялся, когда я использовал 'repaint' или ' обновить », но это другой вопрос.

...