QPlainTextEdit graphical bug on Windows & Linux

63 views Asked by At

I'm writing a simple GUI that displays a live-updating log in a QPlainTextEdit.

This is the handler I am passing to logging.Logger.addHandler()

class QPlainTextEditLogger(logging.Handler):
    """Modified From: https://stackoverflow.com/questions/28655198/best-way-to-display-logs-in-pyqt"""

    def __init__(self, parent):
        super().__init__()
        self.widget = QPlainTextEdit()
        self.widget.setReadOnly(True)

    def emit(self, record):
        msg = self.format(record)
        self.widget.appendPlainText(msg)
        self.widget.moveCursor(QtGui.QTextCursor.End)

    def write(self, m):
        pass

It properly emits the log entries I'm looking for to the QPlainTextEdit element, however, there is a graphical glitch that persists regardless of platform (or compositing enabled/disabled).
Here's a video of the behaviour:

https://i.imgur.com/DTUbfcM.mp4

The lines are chopped in half unless I manually scroll the box or resize the splitter.

This also happens regardless of whether I implement auto-scrolling in the above snippet a la:

moveCursor(QtGui.QTextCursor.End)

What could be causing this?

Edit: I tried to reproduce this with the below example, but I'm not running into the same issue. I think this may be due to me creating the QPlainTextEdit() in my original code outside of the main window perhaps?

import sys
import time

from PyQt5 import QtWidgets, uic, QtGui
from PyQt5.QtWidgets import QPlainTextEdit
from PyQt5.QtCore import QThread, pyqtSignal

class Worker(QThread):
    newLine = pyqtSignal(str)

    def __init__(self):
        super().__init__()
    
    def run(self):
        for x in range(300):
            self.newLine.emit(f"Testing a very long line so that the words will wrap and hopefully reproduce the issue Testing a very long line so that the words will wrap and hopefully reproduce the issue {x}")
            time.sleep(0.1)


class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.editor = QPlainTextEdit(self)
        self.editor.setReadOnly(True)

        self.button = QtWidgets.QPushButton(self)
        self.button.setText("Go for it")

        self.layout = QtWidgets.QFormLayout()
        self.layout.addChildWidget(self.editor)
        self.layout.addChildWidget(self.button)

        self.button.clicked.connect(self.start_button_pressed)
        self.setCentralWidget(self.editor)
        self.show()

    def add_line(self, msg: str):
        self.editor.appendPlainText(msg)

    def start_button_pressed(self):
        self.worker = Worker()
        self.worker.newLine.connect(self.add_line)
        self.worker.start()

app = QtWidgets.QApplication(sys.argv)
window = Window()
app.exec_()
0

There are 0 answers