如何像在 Qtextedit 中那样在 Qtableview 中启用自动滚动?
How to enable autoscroll in Qtableview like in Qtextedit?
我正在使用 QtableView 和 QStandardItemModel 在 GUI 上显示日志以保持适当的间距并过滤日志。我创建了模型并将数据插入其中。使用 QSortFilterProxyModel 过滤字符串。
self.tableView = QtGui.QTableView(self)
self.model = QtGui.QStandardItemModel(self)
self.proxy = QtGui.QSortFilterProxyModel(self)
self.proxy.setSourceModel(self.model)
self.tableView.setModel(self.proxy)
一秒钟内,预计将有近 100 条日志显示在 GUI 上。附加新日志时,视图不会自动滚动并且滑块仅停留在顶部。它不会为日志记录提供实时感觉,用户需要手动滚动到末尾。所以为了克服这个问题,我使用了以下语法,
self.model.rowsInserted.connect(lambda: QtCore.QTimer.singleShot(5, self.tableView.scrollToBottom))
它为日志提供了生动的感觉,但滑块始终位于底部,我无法向上滚动以查看以前的日志。每当我尝试移动滑块时,它会立即再次降到底部。所以这个语法不符合我的要求。在 QTextEdit 中,自动滚动是正确的并且用户友好。我想在 QtableView 上使用相同的场景。是否有类似 QTextEdit 的自动滚动替代方案?
要获得所需的行为,您可以仅在上一个滚动位置位于底部时自动滚动。这样,每当用户滚动离开底部时,自动滚动将被禁用;但是当他们滚动回底部时,将重新启用自动滚动。 (注意:要快速重新启用自动滚动,请右键单击滚动条并从上下文菜单中选择 select "Bottom")。
这是一个简单的演示:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.table = QtGui.QTableView(self)
self.model = QtGui.QStandardItemModel(self)
self.table.setModel(self.model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.table)
self._scroll = True
self.model.rowsAboutToBeInserted.connect(self.beforeInsert)
self.model.rowsInserted.connect(self.afterInsert)
def beforeInsert(self):
vbar = self.table.verticalScrollBar()
self._scroll = vbar.value() == vbar.maximum()
def afterInsert(self):
if self._scroll:
self.table.scrollToBottom()
def addRow(self):
self.model.appendRow([QtGui.QStandardItem(c) for c in 'ABC'])
if __name__ == '__main__':
app = QtGui.QApplication([''])
window = Window()
window.setGeometry(500, 50, 400, 300)
window.show()
timer = QtCore.QTimer()
timer.timeout.connect(window.addRow)
timer.start(200)
app.exec_()
我正在使用 QtableView 和 QStandardItemModel 在 GUI 上显示日志以保持适当的间距并过滤日志。我创建了模型并将数据插入其中。使用 QSortFilterProxyModel 过滤字符串。
self.tableView = QtGui.QTableView(self)
self.model = QtGui.QStandardItemModel(self)
self.proxy = QtGui.QSortFilterProxyModel(self)
self.proxy.setSourceModel(self.model)
self.tableView.setModel(self.proxy)
一秒钟内,预计将有近 100 条日志显示在 GUI 上。附加新日志时,视图不会自动滚动并且滑块仅停留在顶部。它不会为日志记录提供实时感觉,用户需要手动滚动到末尾。所以为了克服这个问题,我使用了以下语法,
self.model.rowsInserted.connect(lambda: QtCore.QTimer.singleShot(5, self.tableView.scrollToBottom))
它为日志提供了生动的感觉,但滑块始终位于底部,我无法向上滚动以查看以前的日志。每当我尝试移动滑块时,它会立即再次降到底部。所以这个语法不符合我的要求。在 QTextEdit 中,自动滚动是正确的并且用户友好。我想在 QtableView 上使用相同的场景。是否有类似 QTextEdit 的自动滚动替代方案?
要获得所需的行为,您可以仅在上一个滚动位置位于底部时自动滚动。这样,每当用户滚动离开底部时,自动滚动将被禁用;但是当他们滚动回底部时,将重新启用自动滚动。 (注意:要快速重新启用自动滚动,请右键单击滚动条并从上下文菜单中选择 select "Bottom")。
这是一个简单的演示:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.table = QtGui.QTableView(self)
self.model = QtGui.QStandardItemModel(self)
self.table.setModel(self.model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.table)
self._scroll = True
self.model.rowsAboutToBeInserted.connect(self.beforeInsert)
self.model.rowsInserted.connect(self.afterInsert)
def beforeInsert(self):
vbar = self.table.verticalScrollBar()
self._scroll = vbar.value() == vbar.maximum()
def afterInsert(self):
if self._scroll:
self.table.scrollToBottom()
def addRow(self):
self.model.appendRow([QtGui.QStandardItem(c) for c in 'ABC'])
if __name__ == '__main__':
app = QtGui.QApplication([''])
window = Window()
window.setGeometry(500, 50, 400, 300)
window.show()
timer = QtCore.QTimer()
timer.timeout.connect(window.addRow)
timer.start(200)
app.exec_()