PDA

View Full Version : QScrollArea -- Scroll to widget problem



qlands
11th May 2010, 12:52
Hi,

I have a scrollarea that contains buttons. When I add a button to the area and immediately call ensureWidgetVisible for that button, the scrollarea does not moves to the widget however, if I call ensureWidgetVisible from another button it works. Seem to me that it something related to call this function immediately after adding a button.

Here is a code the mimics the error:

main.cpp


#include <QtGui>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);


QWidget window;
window.resize(320, 240);
QScrollArea *scrollArea;
QWidget *scrollAreaWidgetContents_2;
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout_2;

scrollArea = new QScrollArea(&window);
scrollArea->setGeometry(QRect(1, 1, 231, 61));
scrollArea->setWidgetResizable(true);
scrollAreaWidgetContents_2 = new QWidget();
scrollAreaWidgetContents_2->setGeometry(QRect(0, 0, 238, 36));
verticalLayout = new QVBoxLayout(scrollAreaWidgetContents_2);
horizontalLayout_2 = new QHBoxLayout();
verticalLayout->addLayout(horizontalLayout_2);
scrollArea->setWidget(scrollAreaWidgetContents_2);

window.show(); //Will not work

QList<QPushButton *> buttons;
buttons.append(new QPushButton("Button 1",scrollAreaWidgetContents_2));
buttons.append(new QPushButton("Button 2",scrollAreaWidgetContents_2));
buttons.append(new QPushButton("Button 3",scrollAreaWidgetContents_2));
buttons.append(new QPushButton("Button 4",scrollAreaWidgetContents_2));
buttons.append(new QPushButton("Button 5",scrollAreaWidgetContents_2));
int pos;
for (pos = 0; pos<=buttons.count()-1;pos++)
{
buttons[pos]->setGeometry(QRect(80, 330, 112, 26));
}
for (pos = 0; pos<=buttons.count()-1;pos++)
{
horizontalLayout_2->addWidget(buttons[pos]);
}

//window.show(); //Will work

scrollArea->ensureWidgetVisible(buttons[3],0,0);

return a.exec();
}


In this example the ensureWidgetVisible fuction will work depending on where I have the show function.

Any ideas what I am missing? Some refresh before calling ensureWidgetVisible?

Many thanks.

T4ng10r
11th May 2010, 13:28
First - I recommend to read QScrollArea::setWidget. There are some dependencies according to order in which objects are added.
After show() there are some changes and recreation of QScrollArea internal layouts. After that - he can says where selected widgets are and move to that position.
So - create enitre internal widget and then add it as main widget for scrollarea.

qlands
11th May 2010, 13:53
To create the entire internal widget beforehand will work in the given example however, it it will not work for example: if a user clicks on a "Add new" button to add a new element to the scrollview because this changes internal layouts. For example:

Add_new_clicked()


buttons.append(new QPushButton("New button",scrollAreaWidgetContents_2));
buttons[buttons.count()-1]->setGeometry(QRect(80, 330, 112, 26));
horizontalLayout_2->addWidget(buttons[buttons.count()-1]); //Add the new element and it is show in the screen
//How to move to this new element?
scrollArea->ensureWidgetVisible(buttons[buttons.count()-1],0,0); //This does not work.

qlands
12th May 2010, 12:38
I'm replying to my post.

Indeed this happens because the scroll area's widget changes it geometry with every button that is added. Thus, ensureWidgetVisible cannot be called immediately because the scroll area does not know its final size yet. A way around is to subclass a QWidget and emit a signal after the widget size changes (by reimplementing the resizeEvent) + setting this widget as the scroll areas's widget. After connecting the signal, ensureWidgetVisible can properly scroll to the added widget.

ratzian
15th September 2011, 13:16
Hello :) I had the same problem and managed to fix it quite easy: Call qApp->processEvents(); before calling the ensureWidgetVisible() method.

The idea is that when the geometry changes, events for doing that are pushed on the event queue... So you execute the events to make the geometry changes and then you can ensure the widget is visible. Of course, these things are happening in the UI thread...

I hope this helps someone out there. Cheers!