【问题标题】:How to set QPlainTextEdit verticalScrollBar to maximum?如何将 QPlainTextEdit verticalScrollBar 设置为最大值?
【发布时间】:2018-07-15 14:55:46
【问题描述】:

考虑一下这个 mcve:

import sys
from datetime import datetime

from PyQt5.Qt import *  # noqa


class Foo(QPlainTextEdit):

    def __init__(self, parent=None):
        super().__init__(parent)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_P:
            self.appendPlainText(f"New line")
        super().keyPressEvent(event)


class FooWindow(QMainWindow):

    def __init__(self, parent=None):
        super().__init__(parent)

        m = self.menuBar().addMenu("&Debug")
        action = QAction("Baz", self)
        action.triggered.connect(self.bar)
        action.setShortcut("Ctrl+N")
        m.addAction(action)

        self.obj = Foo()
        self.obj.setLineWrapMode(QPlainTextEdit.NoWrap)

        for i in range(20):
            self.obj.appendPlainText(f"Line_{i}" * 10)

        self.obj_dock = QDockWidget('Console', self)
        self.obj_dock.setWidget(self.obj)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.obj_dock)

    def bar(self):
        self.obj.appendPlainText(f"New line from menu action")

    def showEvent(self, event):
        bar = self.obj.verticalScrollBar()
        bar.setValue(bar.maximum())
        print(f"2) showEvent {now()}")


def now():
    return datetime.utcnow().strftime('%H:%M:%S.%f')[:-3]


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = FooWindow()
    print(f"1) before show {now()}")
    ex.show()
    print(f"3) after show {now()}")

    # ex.obj.ensureCursorVisible()
    bar = ex.obj.horizontalScrollBar()
    bar.setValue(bar.minimum())
    bar = ex.obj.verticalScrollBar()
    bar.setValue(bar.maximum())

    print(f"4) manual bar.setValue {now()}")

    # timer = QTimer()
    # timer.setInterval(10)
    # timer.setSingleShot(True)
    # def set_scrollbar_at_maximum():
    #     bar = ex.obj.verticalScrollBar()
    #     bar.setValue(ex.obj.verticalScrollBar().maximum())
    #     print(f"5) bar.setValue from timer {now()}")
    # timer.timeout.connect(set_scrollbar_at_maximum)
    # timer.start()

    sys.exit(app.exec_())

我想查看最后添加的行,而不必手动向下滚动垂直条。在ex.show()def showEvent(self, event): 之后调用bar.setValue(ex.obj.verticalScrollBar().maximum()) 不起作用,即:

问题是,除非我手动向下滚动垂直条或使用单次计时器设置值,否则最后添加的行将不可见。

我想知道为什么我上面的 sn-p 不能正常工作,我想知道这些单次计时器的最佳替代品,这些单次计时器具有随机的小间隔......否则,什么是合适的地方这将保证在使用 setValue 等函数后正确绘制子小部件。这东西很令人困惑,人们会期望 showEvent 是一个合适的地方这样做......但它不是:/

【问题讨论】:

    标签: python qt5 pyqt5


    【解决方案1】:

    作为使用单次计时器的替代方法来保证小部件将被正确绘制,似乎覆盖QMainWindow::event 是一个不错的选择,这里有一个可能的问题解决方案:

    import sys
    from datetime import datetime
    
    from PyQt5.Qt import *  # noqa
    
    
    class Foo(QPlainTextEdit):
    
        def __init__(self, parent=None):
            super().__init__(parent)
    
        def keyPressEvent(self, event):
            if event.key() == Qt.Key_P:
                self.appendPlainText(f"New line")
            super().keyPressEvent(event)
    
    
    class FooWindow(QMainWindow):
    
        def __init__(self, parent=None):
            super().__init__(parent)
    
            m = self.menuBar().addMenu("&Debug")
            action = QAction("Baz", self)
            action.triggered.connect(self.bar)
            action.setShortcut("Ctrl+N")
            m.addAction(action)
    
            self.obj = Foo()
            self.obj.setLineWrapMode(QPlainTextEdit.NoWrap)
    
            for i in range(20):
                self.obj.appendPlainText(f"Line_{i}" * 10)
    
            self.obj_dock = QDockWidget('Console', self)
            self.obj_dock.setWidget(self.obj)
            self.addDockWidget(Qt.BottomDockWidgetArea, self.obj_dock)
            self.window_shown = False
    
        def bar(self):
            self.obj.appendPlainText(f"New line from menu action")
    
        def update_widgets(self):
            if self.window_shown:
                return
    
            bar = ex.obj.horizontalScrollBar()
            bar.setValue(bar.minimum())
            bar = self.obj.verticalScrollBar()
            bar.setValue(bar.maximum())
            self.window_shown = True
    
        def event(self, ev):
            ret_value = super().event(ev)
    
            if ev.type() == QEvent.Paint:
                self.update_widgets()
    
            return ret_value
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        ex = FooWindow()
        ex.show()
        sys.exit(app.exec_())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-05
      • 2021-10-15
      • 2017-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      相关资源
      最近更新 更多