PDA

View Full Version : QScrollArea Confusion



TheJim01
24th March 2010, 14:10
I'm trying to learn to use a QScrollArea, but I'm obviously missing some important step.

Using Qt Creator (or designer, it doesn't matter), I create a QMainWindow and add a QScrollArea. I then drop a standard "Widget" into the QScrollArea (and set its style sheet to "background: red;" just so I can see it), and add a standard push button.

I add the following slot to the button:

void MainWindow::on_pushButton_clicked()
{
ui->widget->resize(5000, ui->widget->height());
}
(The rest of the code is generated by Creator, but I can provide it if requested.)

My anticipated behavior is: when I click the button, it will re-size the child widget, thereby causing the scroll area to adjust its scroll bars--in this case only the horizontal bar. Unfortunately, that doesn't happen. I can tell that clicking the button does re-size the child widget, but the scroll area's scroll bars do not update--no handles appear, and the entire scroll bar remains gray, as if disabled.

I have tried enabling the scroll bar, with no effect. I ensured widgetResizable is set to false, but that didn't effect the result either. I originally thought a layout I was using for the child widget was causing the problem, but removing it didn't change the result. The way I understand (or maybe misunderstand) the documentation, by default a QScrollArea should respect the size of its child, and adjust the scroll bars automatically. What did I miss?

TheJim01
24th March 2010, 15:00
Still not fixed, but I've come a little further. Apparently there were conflicting definitions of whether widgetResizable was true or not. I am now 100% sure it is set to false (I checked with a QMessageBox in my clicked() function).

Now, the scroll bar looks active, and there is a large handle in it, regardless of the size of the child widget. When the form is first loaded, the child widget is much smaller than the scroll area, but the big bar is still there. When I click the button, which makes the child widget much wider than the scroll area, the big bar is still there, unchanged.

I'm trying, but I'm obviously still missing some critical step. Any ideas?

TheJim01
24th March 2010, 15:26
I think I figured it out. Creator did something strange in ui_mainwindow.h:
QWidget *centralWidget;
QVBoxLayout *verticalLayout;
QScrollArea *scrollArea;
QWidget *scrollAreaWidgetContents;
QWidget *widget;
QHBoxLayout *horizontalLayout;
QSpacerItem *horizontalSpacer;
QLabel *label;
QLineEdit *widthVal;
QPushButton *pushButton;
QSpacerItem *horizontalSpacer_2;
QSpacerItem *verticalSpacer;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;

void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(407, 205);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
verticalLayout = new QVBoxLayout(centralWidget);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
scrollArea = new QScrollArea(centralWidget);
scrollArea->setObjectName(QString::fromUtf8("scrollArea"));
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(scrollArea->sizePolicy().hasHeightForWidth());
scrollArea->setSizePolicy(sizePolicy);
scrollArea->setMinimumSize(QSize(0, 100));
scrollArea->setMaximumSize(QSize(16777215, 100));
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) ;
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn );
scrollAreaWidgetContents = new QWidget();
scrollAreaWidgetContents->setObjectName(QString::fromUtf8("scrollAreaWidgetContents"));
scrollAreaWidgetContents->setGeometry(QRect(0, 0, 387, 82));
widget = new QWidget(scrollAreaWidgetContents);
widget->setObjectName(QString::fromUtf8("widget"));
widget->setGeometry(QRect(9, 9, 41, 31));
widget->setStyleSheet(QString::fromUtf8("background:red;"));
scrollArea->setWidget(scrollAreaWidgetContents);

...Notice the QWidget pointer "scrollAreaWidgetContents". That becomes the scroll area's child. When my red widget ("widget") was created, "scrollAreaWidgetContents" was passed as its parent. Normally, I would think that "scrollAreaWidgetContents" would act as a pass-through container, since the QScrollArea object doesn't provide a way of defining its child widget through its Creator properties.

Oh well, I'll just have to remember that if I change the UI in the Designer, that I have to change the last line in the code above to
scrollArea->setWidget(widget);

The more I use Creator, the more I see its shortcomings, and the power of hand-coding. Even for fast prototyping (what I'm doing now), I see it's not all that it could be.

Don
19th August 2010, 07:05
[This reply is probably too late for you, but I've seen the same question in a few places, and the doc does not spell it out, so this may benefit others who come looking for an answer. ]

I think you'll find this (http://www.qtforum.org/article/28295/need-help-on-how-to-set-the-inner-widget-of-a-qscrollarea-from-within-qt-designer.html) will achieve the same result.
i.e. right-click on scrollArea : Layout : Lay out Horizontally (or vertically ..)
When scrollArea is created, it is given a scrollAreaWidgetContents, but it has a 'no layout' icon (like the Layout : Break Layout icon).
When scrollAreaWidgetContents has no child, the Layout cannot be set (greyed-out options in Layout menu).

The doc on QScrollArea (http://doc.trolltech.com/4.5/qscrollarea.html#details) has a section on 'Size Hints and Layouts', but I think Qt Designer needs some additional doc that makes this requirement clear.

I was able to prototype this behaviour in Qt Designer, and confirm that this change caused resizing and scrollbars as required.