воскресенье, 17 января 2010 г.

Некоторые особенности QScrollArea

Столкнулся с таким интересным виджетом как QScrollArea. С помощью него можно отображать прокручивающееся содержимое, допустим, картинку или текст, или список виджетов.

Для того, чтобы вовнутрь QScrollArea добавить другой виджет нужно сделать примерно следующее:
// Заранее созданная в setupUi() scrollArea
QLabel *l1 = new QLabel("label1"); 
scrollArea->setWidget(l1);
Метод QScrollArea::setWidget устанавливает наш лейбл l1 в качестве дочернего для scrollArea.

А что, если мы хотим добавить пару лейблов вместо одного.

Вот такой код уже работать правильно не будет - появится только последний лейбл:
QLabel *l1 = new QLabel("label1");
QLabel *l2 = new QLabel("label2"); 
scrollArea->setWidget(l1); 
scrollArea->setWidget(l2);

Для того, чтобы получить два лейбла, нужно использовать слои:
QLabel *l1 = new QLabel("label1"); 
QLabel *l2 = new QLabel("label2");
QVBoxLayout *labelLayout= new QVBoxLayout(scrollArea);
labelLayout->addWidget(l1);
labelLayout->addWidget(l2);
Теперь лейблы будут размещены один под другим.
Либо просто назначить лейблы дочерними по отношению к QScrollArea
QLabel *l1 = new QLabel(scrollArea);
QLabel *l2 = new QLabel(scrollArea);
l1->setText("label1");
l2->setText("label2");
Можно сделать еще и следующим образом:
QLabel *l1 = new QLabel("label1");
QLabel *l2 = new QLabel("label2");
QLabel *l3 = new QLabel("label3");
QVBoxLayout *layout = new QVBoxLayout(scrollArea);
layout ->addWidget(l2);
layout ->addWidget(l3);
ui->scrollArea->setWidget(l1);
Получится 2 лейбла на слое и один не на слое.
Раньше был такой баг - если написать
ui->scrollArea_2->setWidget(l1);
QVBoxLayout *l = new QVBoxLayout(scrollArea);
l->addWidget(l2);
l->addWidget(l3);
то два последних лейбла не отобразятся. Я использую версию Qt4.6, и здесь такого бага уже не наблюдается.

Интересно использование виджета, унаследованного от QScrollArea
Возможно у меня какие-то ошибки, но выяснил следующее...
Допустим имеем:
class RenderArea: public QScrollArea
{
.....
}
то для того, чтобы добавить лейблы надо написать примерно так:
RenderArea::RenderArea(QWidget * pParent) :
    QScrollArea(pParent)
{
    QLabel *l1 = new QLabel(this);
    QLabel *l2 = new QLabel(this);
    l1->setText("label1");
    l2->setText("label2");
    ..............
}
только надо еще разместить их аккуратно, чтобы не перекрывались.
Размещение с помощью setWidget делается как и раньше:
QLabel *l1 = new QLabel("Hello");
this->setWidget(l1);
Либо через слой, если больше одного размещаемого виджета
QLabel *l1 = new QLabel();
QLabel *l2 = new QLabel();
l1->setText("label1");
l2->setText("label2");
QVBoxLayout *layout = new QVBoxLayout(this);
layout ->addWidget(l1);
layout ->addWidget(l2);
и все прекрасно работает.

Очень было б интересно услышать замечания, особенно тех, кто сталкивался с подобным элементом управления и как решал поставленную задачу.

4 комментария :

Bogolt комментирует...

ээ как вам удалось в конструкторе класса создать объект этого же класса? По идее это stack-overflow должен получиться.

Сам же когда нужно много элементов на QScrollArea поместить создаю их все на отдельном QWidget а затем его уже через setWidget указываю как контент для QScrollArea

Руслан комментирует...

To Богольт
Эээ... под "// где-то созданная QScrollArea" я как раз и имел в виду что она создана уже, т.е. внутри setupUi(). Просто по коду получилось, что она тут же создается))). Поправил, спасибо

Unknown комментирует...

Имеется ввиду вот этот код

renderArea = new RenderArea(this);

внутри конструктора RenderArea.

Руслан комментирует...

To Tim
Ну теперь вроде все вычистил. Спасибо!