Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Alex Custov от Июль 28, 2008, 16:29



Название: QScrollArea, динамический виджет
Отправлено: Alex Custov от Июль 28, 2008, 16:29
Имеется вот такой код.. Есть gridlayout с кнопкой "Add" и scrollarea. При нажатии на кнопку Add в scrollarea должна добавляться другая кнопка, однако ничего не происходит. Поправьте где не прав:

Код:
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QHBoxLayout>
#include <QResizeEvent>
#include <QDebug>
#include <QScrollArea>

class ScrollArea : public QScrollArea
{
    Q_OBJECT

    public:
        ScrollArea(QWidget *p) : QScrollArea(p)
        {}

    protected:
        void resizeEvent(QResizeEvent *event)
        {
            qDebug() << event->size();
            QScrollArea::resizeEvent(event);
        }
};

class MyWidget : public QWidget
{
    Q_OBJECT

    public:
        QGridLayout *l;
        ScrollArea  *s;
        QHBoxLayout *layout;

        MyWidget() : QWidget()
        {
            move(0, 0);
            resize(400, 100);

            l = new QGridLayout(this);

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

            s = new ScrollArea(this);

            l->addWidget(b, 0, 0, Qt::AlignCenter);
            l->addWidget(s, 1, 0);

            s->setWidget(new QWidget);

            layout = new QHBoxLayout(s->widget());
            s->widget()->setLayout(layout);
            layout->setDirection(QBoxLayout::LeftToRight);
        }

    private slots:
        void slotC()
        {
            QWidget *w = new QPushButton("b1", s->widget());
            w->setFixedWidth(50);
            w->show();
        }

};

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

    MyWidget *w = new MyWidget;

    w->show();

    return app.exec();
}

#include "main.moc"

P.S. Qt 4.3.3.
P.P.S. Непонятно, куда делся метод QLayout::setAutoAdd() ?


Название: Re: QScrollArea, динамический виджет
Отправлено: spirit от Июль 28, 2008, 16:51
похоже на баг http://trolltech.com/developer/task-tracker/index_html?id=103525&method=entry (http://trolltech.com/developer/task-tracker/index_html?id=103525&method=entry)


Название: Re: QScrollArea, динамический виджет
Отправлено: Alex Custov от Июль 28, 2008, 17:13
Пример очень упрощённый, на самом деле добавляться будет много виджетов, и не только кнопки. И многие - уже после создания интерфейса. Мда, придёться постоянно делать setWidget().

По поводу бага - блин, ну что такое. Столько версий пофиксить не могут. На Qt писать становиться что-то не прикольно :(

Ещё вопрос - в Qt3 был слот

Код:
virtual void resizeContents(int w, int h);

чтобы можно было следить за размерами содержимого. Теперь его нет. Получается, надо наследовать QWidget и отслеживать resizeEvent(), и этот кастомный виджет передавать в QScrollArea::setWidget() ?

Блин, ну зачем так всё усложнять? Раньше как-то попроще было.


Название: Re: QScrollArea, динамический виджет
Отправлено: spirit от Июль 28, 2008, 17:26
можно сделать вот такой воркт-эраунд
Код:
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QHBoxLayout>
#include <QResizeEvent>
#include <QDebug>
#include <QScrollArea>

class ScrollArea : public QScrollArea
{
    Q_OBJECT

    public:
        ScrollArea(QWidget *p) : QScrollArea(p)
        {}

    protected:
        void resizeEvent(QResizeEvent *event)
        {
            //qDebug() << event->size();
            QScrollArea::resizeEvent(event);
        }
};

class MyWidget : public QWidget
{
    Q_OBJECT

    public:
        QGridLayout *l;
        ScrollArea  *s;
        QHBoxLayout *layout;

        MyWidget() : QWidget()
        {
            move(0, 0);
            resize(400, 100);

            l = new QGridLayout(this);

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

            s = new ScrollArea(this);

            l->addWidget(b, 0, 0, Qt::AlignCenter);
            l->addWidget(s, 1, 0);

            s->setWidget(new QWidget);

connect(this, SIGNAL(layoutChanged()), SLOT(updateLayout()), Qt::QueuedConnection);

            layout = new QHBoxLayout(s->widget());
            s->widget()->setLayout(layout);
layout->setDirection(QBoxLayout::LeftToRight);
        }

signals:
void layoutChanged();

    private slots:
        void slotC()
        {
            QWidget *w = new QPushButton("b1", s->widget());
s->widget()->layout()->addWidget(w);           
            w->show();
emit layoutChanged();
        }

void updateLayout()
{
// This is workaround when using QScrollArea::setWidget(...)
// and different widget creation order.
// For more details, please see a bug #103525 on Trolltech Task Tracker:
// http://trolltech.com/developer/task-tracker
int h = s->widget()->sizeHint().height();
int w = s->widget()->sizeHint().width();
s->widget()->resize(w, h);
}

};

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

    MyWidget *w = new MyWidget;

    w->show();

    return app.exec();
}

#include "main.moc"


Название: Re: QScrollArea, динамический виджет
Отправлено: Hort от Июль 29, 2008, 23:15
у меня подобная ситуация - работает все отлично
Код:
answersScrollArea=new QScrollArea;
QWidget *widget=new QWidget;
answersLayout=new QVBoxLayout;
answersLayout->addStretch(1);
slotAddAnswer();
widget->setLayout(answersLayout);
answersScrollArea->setWidget(widget);
answersScrollArea->setWidgetResizable(true);
слот slotAddAnswer() добавлят виджет через
Цитировать
answersLayout->insertWidget(index, new AnswerEditor);
все отлично работает и добавляет динамически во время выполнения программы через тот же самый слот.
единственно с чем промучался и так и не сделал - чтобы скрол ареа прокручивался к добавленному виджету, ели его не видно


Название: Re: QScrollArea, динамический виджет
Отправлено: spirit от Июль 30, 2008, 10:17
так-то работать будет, но в случае сабжа нет, ибо это баг.
когда меняется порядок установки виджетов.
баг номер 103525 на трекере Троллей
Цитировать
Sometimes it will make a difference to Qt when widgets are constructed/added to layouts etc. Most times it will not.

One example is this:


QScrollArea foo(...);
QWidget *w = new QWidget(...);
foo.setWidget(w);
QVBoxLayout *l = new QVBoxLayout(w);
l->addWidget(new QLineEdit);


The line edit does not show up, vs

QScrollArea foo(...);
QWidget *w = new QWidget(...);
QVBoxLayout *l = new QVBoxLayout(w);
l->addWidget(new QLineEdit);
foo.setWidget(w);

where the line edit does show. Similar things happen with QDockWidget::setWidget().