如何将 QPlainTextEdit verticalScrollBar 设置为最大值?
Posted
技术标签:
【中文标题】如何将 QPlainTextEdit verticalScrollBar 设置为最大值?【英文标题】:How to set QPlainTextEdit verticalScrollBar to maximum? 【发布时间】: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 是一个合适的地方这样做......但它不是:/
【问题讨论】:
【参考方案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_())
【讨论】:
以上是关于如何将 QPlainTextEdit verticalScrollBar 设置为最大值?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 QPlainTextEdit verticalScrollBar 设置为最大值?
如何在 QPlainTextEdit 小部件中突出显示整行文本?
如何从 QPlainTextEdit 正确获取 Unicode 文本输入? [复制]
如何知道 QPlainTextEdit 继承类中是不是显示水平滚动条?