I am trying to make the last QPushButton
visible by using method QScrollArea().ensureWidgetVisible()
, but as you can see this method doesn't scroll till the last QPushButton
.
Example
Could you please assist and solve my issue perhaps issue with setFrameStyle? thank you in advance.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setFixedHeight(200)
#Container Widget
widget = QWidget()
#Layout of Container Widget
layout = QVBoxLayout(self)
for _ in range(20):
btn = QPushButton("test")
layout.addWidget(btn)
widget.setLayout(layout)
#Scroll Area Properties
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
# print(scroll.verticalScrollBar().maximum())
# vbar = scroll.verticalScrollBar()
# vbar.setValue(vbar.maximum())
#vbar.setValue(vbar.maximum())
#Scroll Area Layer add
vLayout = QVBoxLayout(self)
vLayout.addWidget(scroll)
self.setLayout(vLayout)
# items = (layout.itemAt(i) for i in range(layout.count()))
# for w in items:
# print(w)
print(layout.count())
#scroll.ensureWidgetVisible(layout.itemAt(layout.count()-5).widget(), xMargin=10, yMargin=10 )
scroll.ensureWidgetVisible(layout.itemAt(layout.count()-1).widget() )
print(layout.itemAt(layout.count()-1).widget(),"last widget")
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
app.exec_()
The problem is that for efficiency reasons widgets sizes are not calculated or updated until they are displayed, in your case the viewport of QScrollArea
has not updated its size and therefore moves the scroll to an intermediate position. A possible solution is to use QTimer::singleShot()
to call the function ensureWidgetVisible()
a moment after it has been displayed:
import sys
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__(parent)
self.setFixedHeight(200)
#Container Widget
widget =QtWidgets.QWidget()
#Layout of Container Widget
layout = QtWidgets.QVBoxLayout(widget)
for _ in range(20):
btn = QtWidgets.QPushButton("test")
layout.addWidget(btn)
scroll = QtWidgets.QScrollArea()
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
#Scroll Area Layer add
vLayout = QtWidgets.QVBoxLayout(self)
vLayout.addWidget(scroll)
last_widget = layout.itemAt(layout.count()-1).widget()
QtCore.QTimer.singleShot(0, partial(scroll.ensureWidgetVisible, last_widget))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = Widget()
dialog.show()
sys.exit(app.exec_())
or simply call show()
before:
...
last_widget = layout.itemAt(layout.count()-1).widget()
self.show()
scroll.ensureWidgetVisible(last_widget)