PDA

View Full Version : Auto scroll down in QScrollArea



EricF
24th December 2008, 15:24
Hi, I've made a search and found lots of answer but I still can't get it to work. I'm toying with the scroll area in which I want to add widget to it dynamically and I want the scroll area to ensure the las widget is always visible.

I use a widget in which I use a QVBoxLayout and then set this widget in the scroll area. I can see my stuff but it always scrolls to the next to last one when I use ensureWidgetVisible. I traced this method and the size hint returned seems ok. Here's my test code:



#include <QApplication>
#include <QtGui>

#include "MainWidget.h"

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

// Put your own widget here.
MainWidget* w = new MainWidget();
w->show();

return app.exec();
}




#pragma once

#include <QtGui>

class MainWidget : public QWidget
{
Q_OBJECT

public:
MainWidget( QWidget* parent = 0 );


public slots:
void OnNewElement();

protected slots:
void ScrollToEnd();

protected:
QScrollArea* mScrollArea;
QWidget* mInternalWidget;
QVBoxLayout* mInternalLayout;
QWidget* mLastChild;
};




#include "MainWidget.h"

MainWidget::MainWidget( QWidget* parent ) : QWidget(parent)
{
QHBoxLayout* layout = new QHBoxLayout(this);
setLayout( layout );

mScrollArea = new QScrollArea(this);
layout->addWidget( mScrollArea );

mInternalWidget = new QWidget(mScrollArea);
mInternalLayout = new QVBoxLayout(mInternalWidget);
mInternalWidget->setLayout(mInternalLayout);

QWidget* element = NULL;
for (int i=0; i<20; ++i)
{
QString name = QString("Base Element %0").arg(i);
element = new QWidget( mInternalWidget );
element->setFixedSize( 200,20 );

element->setAutoFillBackground( true );
QPalette p = element->palette();
p.setColor( QPalette::Window, QColor(255,0,255) );
element->setPalette(p);

mInternalLayout->addWidget( element );
}

mScrollArea->setWidget( mInternalWidget );
mScrollArea->setWidgetResizable(true);
mScrollArea->verticalScrollBar()->setSingleStep( 20 );

QPushButton* b = new QPushButton( "Add new element" );
connect( b, SIGNAL(clicked()), this, SLOT(OnNewElement()) );

layout->addWidget( b );
}

void MainWidget::OnNewElement()
{
static int count = 0;
QString name = QString("New Element %0").arg(count++);
QLabel* element = new QLabel( name );
element->setFixedSize( 100, 20 );

element->setAutoFillBackground( true );
QPalette p = element->palette();
p.setColor( QPalette::Window, QColor(255,0,0) );
element->setPalette(p);

mInternalLayout->addWidget( element );
mLastChild = element;
QTimer::singleShot( 5, this, SLOT(ScrollToEnd()) );
}

void MainWidget::ScrollToEnd()
{
//mScrollArea->verticalScrollBar()->setValue( mScrollArea->verticalScrollBar()->maximum() );
mScrollArea->ensureWidgetVisible( mLastChild );
}


Calling ensureWidgetVisible from the OnNewElement slot does not work and I suspected that is was because the layout had not been calculated yet so I tried a singleShot timer to do the scroll. It works for the first 100 or so elements but after that, it scrolls to the next to last element again.

I know we're on the 24th but you know the drill, coders almost always work :o

ntp
24th December 2008, 23:45
Did you try setting the margins = 0?



mScrollArea->ensureWidgetVisible( mLastChild , 0, 0);

EricF
29th December 2008, 13:51
Yeah tried it too but it doesn't work either.