我有一个 QScrollArea,我希望当我按下“添加”按钮时,将小部件添加到 QScrollArea 中包含的小部件中,以便滚动一直滚动到底部
我多次尝试使用类似代码滚动到底部
scrollWidget.update()
bar = scrollWidget.verticalScrollBar()
bar.setValue(bar.maximum())
或者甚至使用
ensureWidgetVisible
但似乎发生的事情是它滚动到滚动的底部“在调整大小发生之前”,然后它调整大小,所以我不太在底部。
我通过编写检查条形大小、最大条形大小和子项计数的代码来验证这一点 这表明有新的子项,但条形大小尚未更新。
然后我尝试先通过调用给 Qt 时间“重新计算”大小:
QApplication.processEvents()
scrollWidget.update()
我不希望滚动区域始终位于底部,但仅在按下按钮后
我不得不处理同样的问题,我找到了一个我认为很好的解决方案,尽管我是 Qt 新手,所以对此持保留态度:
class MyMainWindow(QWidget):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.scrollarea = QScrollArea()
# [...]
self.vscrollbar = self.scrollarea.verticalScrollBar()
self.vscrollbar.rangeChanged.connect(self.scrollToBottom)
@Slot(int, int)
def scrollToBottom(self, minimum, maximum):
self.vscrollbar.setValue(maximum)
在构建过程中,我们将
rangeChanged
信号连接到我们的自定义插槽scrollToBottom
,将滚动值设置为最大值,从而在每次内容垂直增长时向下滚动到底部。
我更进一步,如果在内容增长之前视图一直滚动到底部,则仅滚动到底部:
class MyMainWindow(QWidget):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.scrollarea = QScrollArea()
# [...]
self.vscrollbar = self.scrollarea.verticalScrollBar()
self.vscrollbar.rangeChanged.connect(self.scrollToBottomIfNeeded)
self.vscrollbar.valueChanged.connect(self.storeAtBottomState)
self.atbottom = True
@Slot(int)
def storeAtBottomState(self, value):
self.atbottom = value == self.vscrollbar.maximum()
@Slot(int, int)
def scrollToBottomIfNeeded(self, minimum, maximum):
if self.atbottom:
self.vscrollbar.setValue(maximum)
在我的应用程序的上下文中,这是首选行为,因为当用户在 ScrollArea 中查看某些内容时,内容会增长,因此自动滚动会阻止它们停留在原来的位置。如果您的应用程序仅在用户操作后增加内容,请使用第一个片段中的方法。
响应您的评论,这是添加元素时仅向下滚动的方法:
class MyMainWindow(QWidget):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.scrollarea = QScrollArea()
self.addbutton = QPushButton()
self.addbutton.clicked.connect(self.addElement)
# [...]
self.vscrollbar = self.scrollarea.verticalScrollBar()
self.vscrollbar.rangeChanged.connect(self.scrollToBottomIfNeeded)
self.adding = False
@Slot()
def addElement(self):
self.adding = true
# ... actually add an element ...
@Slot(int, int)
def scrollToBottomIfNeeded(self, minimum, maximum):
if self.adding:
self.vscrollbar.setValue(maximum)
self.adding = False
我做了一些实验,改变了方法调用的顺序。但我仍然不明白到底什么时候值得调用滚动更改。我写了糟糕的代码,但它有效。
def scroll_to_bottom(self):
for i in range(2): # range(3) or range(4), range(2) works for me
QApplication.processEvents()
self.scrollArea_messages.update()
cur_max = self.scrollArea_messages.verticalScrollBar().maximum()
self.scrollArea_messages.verticalScrollBar().setValue(cur_max)