Russian Qt Forum
Июнь 03, 2024, 19:09 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QLayout + minimumSize, изменяющийся динамически = рак мозга  (Прочитано 7696 раз)
ритт
Гость
« : Июль 27, 2008, 03:22 »

написал лэйоут, функционально похожий на examples/layouts/flowlayout.
метод minimumSize, ответственный за минимальный размер, возвращает максимальные ширину и высоту виджетов из списка + маржины
Код:
QSize FlowLayout::minimumSize() const
{
    QSize size;
    QLayoutItem *item;
    foreach (item, itemList)
        size = size.expandedTo(item->minimumSize());

    size += QSize(2*margin(), 2*margin());
    return size;
}
но если подсунуть этот лэйут виджету, на котором расположены ещё какие-нибудь виджеты, некорректное вычисление минимального размера сразу станет заметно - виджеты фловлэйоута будут пересекаться с виджетами на "родных" лэйоутах (которые нормально рассчитывают размеры)

в этом как раз и проблема - никак не удаётся реализовать правильный обсчёт. когда опрашивается minimumSize, геометрия уже сброшена и мы просто не знаем какие ширина/высота были удовлетворительными секунду назад чтобы вернуть их в качестве временного минимального размера.
если, например, минимальный размер может измениться в зависимости от размера, переданного в setGeometry, то как уведомить виджет о том, что его минимальный размер изменился и виджет должен соответствующим образом пересчитать собственную геометрию?! parentWidget()->updateGeometry() не помогает...апдейт, инвалидэйт, постИвент - чего я только уже не пробовал.
не могу сообразить каким макаром минимальный размер учитывается для верхнего виджета при каждом ресайзе, а для дочернего - лишь по праздникам...рррррррр Грустный
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Июль 27, 2008, 11:48 »

Цитировать
метод minimumSize, ответственный за минимальный размер, возвращает максимальные ширину и высоту виджетов из списка + маржины
в статье "Классы компоновки" написано:
"sizeHint() и minimumSize() обычно имеют очень похожие реализации. Размеры, возвращаемые обеими функциями, должны включать spacing(), но не должны включать margin(). "
Записан

Юра.
ритт
Гость
« Ответ #2 : Июль 27, 2008, 15:04 »

у троллей сайзХинт, минимумСайз и максимумСайз включают margin

Код:
void QBoxLayoutPrivate::setupGeom()
//...
    minSize = QSize(minw, minh);
    maxSize = QSize(maxw, maxh).expandedTo(minSize);
    sizeHint = QSize(hintw, hinth).expandedTo(minSize).boundedTo(maxSize);

    q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
    int left, top, right, bottom;
    effectiveMargins(&left, &top, &right, &bottom);
    QSize extra(left + right, top + bottom);

    minSize += extra;
    maxSize += extra;
    sizeHint += extra;
//...

QSize QBoxLayout::sizeHint() const
{
    Q_D(const QBoxLayout);
    if (d->dirty)
        const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
    return d->sizeHint;
}

но это к теме не относится. вопрос остаётся открытым: как лэйуоту заставить виджет пересчитать ограничивающие размеры?
« Последнее редактирование: Июль 27, 2008, 17:18 от Константин » Записан
Alex03
Гость
« Ответ #3 : Июль 28, 2008, 11:28 »

А что за виджеты внутри Вашего лэйаута?
Воpвращают ли они корректный minimumSize?
Может так:
Код:
    foreach (item, itemList)
    {
        size = size.expandedTo(item->minimumSize());
        size = size.expandedTo(item->minimumSizeHint());
    }
Да и ИМХО не логично это, это минимальные размеры по каждой оси, но не совместные.
Но видимо дело не в этом...

Этот лэйаут засунут в виджет, а виджет в другой лэйаут или как?
Константин, минимальный примерчик компилябельный забубень, совместно поковыряемся. Улыбающийся

С вложенными лэйаутами "особенностей" тоже хватает...
А уж с hasHeightForWidth()/heightForWidth(int width) тожа не всё гладко.
Записан
ритт
Гость
« Ответ #4 : Июль 28, 2008, 14:26 »

>  size = size.expandedTo(item->minimumSizeHint());
у QLayoutItem нет метода minimumSizeHint
действительно, это нелогично, но работает именно так, как требуется...пока этот лэйоут установлен на топ-виджет

минимальный пример - examples/layouts/flowlayout.
попробуй заменить
Код:
Window::Window()
{
    FlowLayout *flowLayout = new FlowLayout;

    flowLayout->addWidget(new QPushButton(tr("Short")));
    flowLayout->addWidget(new QPushButton(tr("Longer")));
    flowLayout->addWidget(new QPushButton(tr("Different text")));
    flowLayout->addWidget(new QPushButton(tr("More text")));
    flowLayout->addWidget(new QPushButton(tr("Even longer button text")));
    setLayout(flowLayout);

    setWindowTitle(tr("Flow Layout"));
}
на
Код:
Window::Window()
{
QWidget* widget = new QWidget();
    FlowLayout *flowLayout = new FlowLayout;

    flowLayout->addWidget(new QPushButton(tr("Short")));
    flowLayout->addWidget(new QPushButton(tr("Longer")));
    flowLayout->addWidget(new QPushButton(tr("Different text")));
    flowLayout->addWidget(new QPushButton(tr("More text")));
    flowLayout->addWidget(new QPushButton(tr("Even longer button text")));
    widget->setLayout(flowLayout);

QGridLayout* layout = new QGridLayout;
    layout->addWidget(widget, 0, 0);
    layout->addWidget(new QPushButton(tr("Even longer button text")), 1, 1);
    setLayout(layout);

    setWindowTitle(tr("Flow Layout"));
}
если ничего более не менять, баттоны из фловлэйоута при ресайзе поползут на область следующей строки гридлэйоута. если у фловлэйоута в минимумСайз учитывать высотуДляШирины, эта высота зафиксируется и при ресайзе высоту нельзя будет установить меньше, хотя фактическая высота уменьшилась
Записан
Alex03
Гость
« Ответ #5 : Июль 29, 2008, 06:32 »

минимальный пример - examples/layouts/flowlayout.
попробуй заменить на ....
ХМ... Работает нормально. Qt 4.3.3 Win XP.

Так тоже всё ОК:
Код:
Window::Window()
{
//    QWidget* widget = new QWidget();
    FlowLayout *flowLayout = new FlowLayout;

    flowLayout->addWidget(new QPushButton(tr("Short")));
    flowLayout->addWidget(new QPushButton(tr("Longer")));
    flowLayout->addWidget(new QPushButton(tr("Different text")));
    flowLayout->addWidget(new QPushButton(tr("More text")));
    flowLayout->addWidget(new QPushButton(tr("Even longer button text")));
//    widget->setLayout(flowLayout);

    QGridLayout* layout = new QGridLayout;
//    layout->addWidget(widget, 0, 0);
    layout->addLayout(flowLayout, 0, 0);
    layout->addWidget(new QPushButton(tr("Even longer button text")), 1, 1);
    setLayout(layout);

    setWindowTitle(tr("Flow Layout"));
}
Записан
ритт
Гость
« Ответ #6 : Июль 29, 2008, 07:29 »

блиаааааа...иптить!!!
попробуй в этом же примере сделать Виндов наследником кумэйнвиндов
Код:
class Window : public QMainWindow
{
//...snip
//...unchanged

QWidget* cw = new QWidget();
cw->setLayout(layout);
setCentralWidget(cw);

    setWindowTitle(tr("Flow Layout"));
}

ну, или даже проще - с минимальными изменениями:
Код:
{
    QWidget* widget = new QWidget();
    FlowLayout *flowLayout = new FlowLayout;

    flowLayout->addWidget(new QPushButton(tr("Short")));
    flowLayout->addWidget(new QPushButton(tr("Longer")));
    flowLayout->addWidget(new QPushButton(tr("Different text")));
    flowLayout->addWidget(new QPushButton(tr("More text")));
    flowLayout->addWidget(new QPushButton(tr("Even longer button text")));
    widget->setLayout(flowLayout);

setCentralWidget(widget);

    setWindowTitle(tr("Flow Layout"));
}
« Последнее редактирование: Июль 29, 2008, 07:50 от Константин » Записан
Alex03
Гость
« Ответ #7 : Июль 29, 2008, 08:14 »

Угу... Глючит...
В файлах
  • qdockarealayout.cpp
  • qdockarealayout_p.h
  • qmainwindowlayout.cpp
  • qmainwindowlayout_p.h
  • qmainwindow.cpp
  • qmainwindow.h
нет упоминаний про heightForWidth. Грустный

Такая вот багофича.... Грустный Грустный Грустный
Записан
ритт
Гость
« Ответ #8 : Июль 29, 2008, 16:12 »

классно! обалдеть...
я на это два вечера угрохал и безрезультатно Грустный
наклепаю репорт и потом отпишусь
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 19.