My Qt application, which I am writing in PyQt6, contains a QGraphicsView
. Depending on the size of the application window, the QGraphicsScene
underlying this view may be too big to fit in the viewport, so the QGraphicsView
automatically adds horizontal and vertical scrollbars as necessary.
I find that when I resize the window to be wide enough that the horizontal scrollbar ought to no longer be necessary, the QGraphicsView
doesn't move the vertical scrollbar over into the excess space, and therefore I continue to have a horizontal scrollbar present, which only scrolls by an amount equal to the width of the vertical scrollbar.
When there is sufficient space horizontally, I'd like for the vertical scrollbar of my QGraphicsView
to appear to the right of the view, rather than within it, so that a horizontal scrollbar is unnecessary.
(I think this is what QScrollArea.setWidgetResizable(True)
is supposed to do, but unfortunately, QGraphicsView
subclasses from QAbstractScrollArea
rather than QScrollArea
so the widgetResizable
property is not available.)
How can I make that horizontal scrollbar stop appearing in circumstances where it isn't needed?
MWE:
from PyQt6 import QtCore, QtGui, QtWidgets
class MyBottomWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
scene = QtWidgets.QGraphicsScene()
rect = QtCore.QRect(0, 0, 700, 700)
shape = scene.addEllipse(rect)
shape.setBrush(QtGui.QColor(QtGui.QColorConstants.Blue))
view = QtWidgets.QGraphicsView(scene)
view.setSceneRect(rect)
view.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)
layout = QtWidgets.QGridLayout(self)
self.setLayout(layout)
layout.addWidget(view, 0, 0, QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignTop)
app = QtWidgets.QApplication([])
window = QtWidgets.QMainWindow()
window.resize(800, 600)
window.setCentralWidget(MyBottomWidget())
window.show()
app.exec()
The solution I came up with was to subclass
QGraphicsView
and override thesizeHint
method to always include the extent of the scrollbar in the width and height.Using
MyGraphicsView
instead ofQtWidgets.QGraphicsView
in my code, I now get the following behavior:Not a perfect solution due to point 1 — ideally if there's plenty of space so that scrollbars aren't needed, then the canvas wouldn't have the extra 19px included — but totally satisfactory for my needs. If desired, one could add rectangles in the default background color to the right and bottom edges of the scene to disguise the fact that those extra pixels are included:
I've decided against doing this for the time being but it's something one could play with.