【问题标题】:drawText causing problems when scrolling in QTextEdit在 QTextEdit 中滚动时导致出现问题的 drawText
【发布时间】:2021-03-17 15:38:49
【问题描述】:

我有一个自定义文本框,它显示文本框右上角的字符数。 我通过继承 QTextEdit 并覆盖绘制事件并使用 QPainter 绘制字符数来做到这一点。

问题在于,当滚动绘画时,会出现扭曲并显示多个字符数。使用滚动条而不是鼠标滚轮滚动时可以更清楚地看到问题。

这是我的代码。

from PyQt5 import QtWidgets, QtCore, QtGui
import sys


class TextBox(QtWidgets.QTextEdit):

    def __init__(self, maxChar=1000, *args, **kwargs):
        super(TextBox, self).__init__(*args, **kwargs)

        self.charCount = 0
        self.maxChar = maxChar

        self.painter_font = self.font()
        self.painter_font.setFamily('')
        self.painter_font.setPointSize(5)

        self.textChanged.connect(self.changeCount)

    def changeCount(self):
        self.charCount = len(self.toPlainText())

    def keyPressEvent(self, event):

        if self.charCount < self.maxChar:
            super(TextBox, self).keyPressEvent(event)

        if self.charCount >= self.maxChar:
            if event.key() in [QtCore.Qt.Key_Backspace, QtCore.Qt.Key_Delete, QtCore.Qt.Key_Up,
                               QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Down]:
                super(TextBox, self).keyPressEvent(event)

            if event.key() & QtCore.Qt.Key_A and event.modifiers() & QtCore.Qt.ControlModifier:
                super(TextBox, self).keyPressEvent(event)

    def paintEvent(self, event):
        super(TextBox, self).paintEvent(event)

        painter = QtGui.QPainter(self.viewport())
        painter.setFont(self.painter_font)

        painter.setPen(QtGui.QColor(QtCore.Qt.red))
        count = f'{self.charCount}/{self.maxChar}'

        multiplier = 4
        if self.verticalScrollBar().isVisible():
            multiplier = 8

        painter.drawText(QtCore.QPoint(self.width() - (len(count) * multiplier + 30), self.height() - 10), count)  # This is to make sure that the count stays inside the textbox when the number increases. If you have a better way pls help.


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    win = TextBox()
    win.show()

    sys.exit(app.exec_())

问题图片:

【问题讨论】:

  • 您可以尝试使用标签来显示计数并在发生调整大小事件或其中一个滚动条变得可见时调整其位置。
  • TextEdit 内的@Heike 标签?
  • 是的,让标签成为 TextEdit 的子标签并覆盖 TextEdit 的 resizeEvent。

标签: python pyqt pyqt5


【解决方案1】:

这里演示了如何使用标签在文本上打印字符数

class TextBox(QtWidgets.QTextEdit):

    def __init__(self, maxChar=1000, *args, **kwargs):
        super(TextBox, self).__init__(*args, **kwargs)

        self.charCount = 0
        self.maxChar = maxChar

        self.textChanged.connect(self.changeCount)

        # add a label to self.
        self.label = QtWidgets.QLabel('', self)
        self.label.setFixedSize(150, 15)
        self.label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom)
        font = self.font()
        font.setPointSize(8)
        self.label.setFont(font)
        palette = self.label.palette()
        palette.setColor(palette.WindowText, QtGui.QColor("red"))
        self.label.setPalette(palette)
        self.changeCount()

    # the label text is updated when character count is changed   
    def changeCount(self):
        self.charCount = len(self.toPlainText())
        self.label.setText(f'{self.charCount}/{self.maxChar}')

    # The position of the label needs to be updated manually when the size of the text box changes     
    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.label.move(event.size().width()-self.label.width(), event.size().height()-self.label.height())

    def keyPressEvent(self, event):

        if self.charCount < self.maxChar:
            super(TextBox, self).keyPressEvent(event)

        if self.charCount >= self.maxChar:
            if event.key() in [QtCore.Qt.Key_Backspace, QtCore.Qt.Key_Delete, QtCore.Qt.Key_Up,
                               QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Down]:
                super(TextBox, self).keyPressEvent(event)

            if event.key() & QtCore.Qt.Key_A and event.modifiers() & QtCore.Qt.ControlModifier:
                super(TextBox, self).keyPressEvent(event)

【讨论】:

  • 嘿,谢谢你的回答,你能解释一下为什么绘画事件会导致问题吗?
  • 小部件并不总是更新其所有内容,尤其是基于 QAbstractScrollArea 的小部件,这是为了优化性能:它们只更新实际需要重新绘制的部分,其中还包括 清除以前的画。在您的情况下,之前绘制文本的区域不会清除,因此之前文本的某些部分仍然可见。您可以使用活动的rect()region() 查看实际更新区域。作为替代方案,您可以在垂直位置发生变化时强制执行计划的完全重绘 (self.viewport().update())。
  • @musicamante 感谢评论。还有一个问题是使用标签比在文本框中绘制文本更好? (回复时请标记我)
  • 这取决于您,这完全取决于具体情况,您需要考虑性能和代码的简单性来评估什么更好。 (标记并不总是需要:在这种情况下,由于您是唯一的评论者,无论如何您都会收到通知,as explained on meta
  • @musicamante 我没有收到任何通知,包括你刚才评论的那个。
猜你喜欢
  • 1970-01-01
  • 2017-11-03
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多