Qscrollarea Missing Scrollbar

QScrollArea missing Scrollbar

You do not want to set the layout on the scroll area itself. The answer you cite stems from misunderstanding this.

  1. You need to have a widget within a scrollarea, and you pass that widget to the area using QScrollArea::setWidget. If all you have inside the scroll area is one widget with no children, then you don't need additional layout.

  2. You do not need to manually keep track of widgets that are owned by a layout. They'll be deleted automatically once the widget that has the layout is deleted.

  3. The QScrollArea widget is not laid out within its enclosing widget.

Below is a working example of how to do it:

// https://github.com/KubaO/stackoverflown/tree/master/questions/scroll-18703286
#include <QScrollArea>
#include <QVBoxLayout>
#include <QSpinBox>
#include <QApplication>

class Window : public QWidget
{
QVBoxLayout m_layout{this};
QScrollArea m_area;
QWidget m_contents;
QVBoxLayout m_contentsLayout{&m_contents};
QSpinBox m_spinBoxes[10];
public:
Window(QWidget *parent = {}) : QWidget(parent) {
m_layout.addWidget(&m_area);
m_area.setWidget(&m_contents);
for (auto & spinbox : m_spinBoxes)
m_contentsLayout.addWidget(&spinbox);
m_contentsLayout.setSizeConstraint(QLayout::SetMinimumSize);
}
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window w;
w.show();
return app.exec();
}

How to use QScrollArea to make scrollbars appear

Since many questions wonder how to use a QScrollArea that many widgets have, I will take the license to explain the various forms in detail and use them as a canonical answer for future readers.

QScrollArea only allows placing a container widget so the other widgets must be placed as children of the container widget.

And to place the widgets as children of another there are 2 possibilities:

1. Use a QLayout:

QLayouts allow you to automate the geometry of the widgets based on the QSizePolicy, strecth, sizeHint, etc. So in that case it's simple: Just set the widgetResizable property to True.

import sys
from PyQt5 import QtWidgets

class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)

central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)

scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(True)

container = QtWidgets.QWidget()
scroll_area.setWidget(container)

# Set widgets via layout
lay = QtWidgets.QVBoxLayout(container)
lay.setContentsMargins(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text)
lay.addWidget(label)
lay.addStretch()

self.setGeometry(300, 300, 803, 520)

if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

2. Set the widgets directly without layouts:

In this case you must calculate the minimum geometry that contains the internal widgets and set the size in the container, also you must set the widgetResizable property to False:

import sys
from PyQt5 import QtCore, QtWidgets

class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)

central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)

scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(False)

container = QtWidgets.QWidget()
scroll_area.setWidget(container)

# calculate geometry
geometry = QtCore.QRect(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text, container)
label.adjustSize()
label.move(geometry.bottomLeft())
geometry |= label.geometry()

geometry.setTopLeft(QtCore.QPoint(0, 0))
container.resize(geometry.size())

self.setGeometry(300, 300, 803, 520)

if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

Scroll bars with QScrollArea

In Designer, in your QScrollArea uncheck widgetResizable property or use QScrollArea::setWidgetResizable to turn it off programatically.

QScrollArea: horizontal scrollbar caused by vertical scrollbar

Not so much a solution as it is a workaround, but it works.

iconFrame->adjustSize(); // Only necessary when contents of iconFrame have changed
if(iconFrame->height() > scroll->height())
scroll->setMinimumWidth(iconFrame->width()+scroll->verticalScrollBar()->height());

Qt Scroll Area does not add in scroll bars

You need to add your horizontalWidget to a vertical widget like so:

QVBoxLayout* vLayout = new QVBoxLayout();

for (int i = 0; i < numberOfSlices; i++)
{
QWidget *horizontalWidget = new QWidget();
vLayout->addWidget(horizontalWidget);
....
}
scrollAreaWidgetContents->setLayout(vLayout);

You second problem looks like it comes from this line:

scrollArea = new QScrollArea(verticalWidget);

You're adding scrollArea directly to verticalWidget, but to get it to lay out the way you want you need to put it in a layout. Try the following instead:

QVBoxLayout* l = new QVBoxLayout();
l->addWidget(sliceLabel); // or whatever you call it
l->addWidget(scrollArea);
l->addWidget(clearButton); // again, your name here
verticalWidget->setLayout(l);

How to resize QScrollArea when a scrollbar appears (so only one bar is necessary)?

I had a similar situation, which was solved by overriding QScrollArea::sizeHint() in the descendant.

#include <QScrollBar>
#include <QScrollArea>

class MyScrollArea : public QScrollArea
{
Q_OBJECT

public:
QSize sizeHint() const override
{
auto newSize = QScrollArea::sizeHint();
newSize.setWidth(newSize.width()
+ verticalScrollBar()->sizeHint().width());
return newSize;
}
};

Preventing a QScrollArea from displaying a horizontal Scroll bar

Set the proper horizontal size policies for your dynamically created frames while creating them. One option is fixed size (QSizePolicy::Fixed), the other is QSizePolicy::Maximum (it's not very intuitive, but actually maximum means that the frame won't be bigger than the size specified by sizeHint() function). If you want the widget to expand vertically, set the vertical size policy to QSizePolicy::MinimumExpanding or QSizePolicy::Expanding - whatever works for you.



Related Topics



Leave a reply



Submit