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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: [Лэйауты] Хочется странного  (Прочитано 23571 раз)
SLiDER
Гость
« : Октябрь 09, 2009, 16:28 »

Вот появилась у меня нужда создать следующую раскладку виджетов (см. приложенную картинку). В двух словах проблема следующая. Есть (допустим) три виджета: верхний, левый и правый; уложенные в QGridLayout по следующей схеме, верхний - лежит в нулевой и первой ячейках нулевго ряда, ну, а левый и правый под ним в нулевой и первой ячейках первого ряда соотвественно (опять же см. рисунок). Необходимо скрывать и показывать правый виджет, по нажатию на кнопку расположенную на левом виджете, так что бы после того как правый виджет был показан а затем скрыт, диалог возвращался к первозданному виду.
Утрахался уже, может у кого есть какие мысли на эту тему, просьба поделиться.
К посту кроме картинки прикладываю тестовый проект, так что можно потренироваться Улыбающийся
Записан
andrewshkovskii
Гость
« Ответ #1 : Октябрь 09, 2009, 16:53 »

Может попробовать сплиттер запихнуть между колонкой с кнопкой и самим "двигающимся" виджетом? При нажатии кнопки сплиттер отодвигать и прятать, при повторном возвращать в было состояние, и фильтровать ивенты сплиттера на ручное его передвижение?
Записан
Mitchel
Гость
« Ответ #2 : Октябрь 09, 2009, 18:22 »

есть вариант (может не совсем красивый) при show сохранять размены окна, а при нажатии hide устанавливать сохранённые размеры
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #3 : Октябрь 09, 2009, 18:27 »

В книге Бланшетте есть пример, реализующий такой диалог (More >>)
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
SLiDER
Гость
« Ответ #4 : Октябрь 10, 2009, 00:04 »

есть вариант (может не совсем красивый) при show сохранять размены окна, а при нажатии hide устанавливать сохранённые размеры

А Вы проект приложенный посмотрите, там попытка поступить именно таким образом, ни х.... ни получается, ибо при вызове setVisible(false), реальные размеры спрятываемого виджета, реально меняются х.з. когда, но не сразу после вызова этой функции, а так как у него установлен минимальный размер и весьма большой то и попытка изменения размера диалога не проходит.
Записан
SLiDER
Гость
« Ответ #5 : Октябрь 10, 2009, 00:09 »

В книге Бланшетте есть пример, реализующий такой диалог (More >>)

Здравствуйте капитан Очевидность, какими судьбами Улыбающийся К сожалению в данном случае вся мощь разума господина Бланшетте не в состоянии помочь моей беде. Неверите Непонимающий Попробуйте реализовать, тестовый проект я приложил. Улыбающийся
Записан
SLiDER
Гость
« Ответ #6 : Октябрь 10, 2009, 00:14 »

Может попробовать сплиттер запихнуть между колонкой с кнопкой и самим "двигающимся" виджетом? При нажатии кнопки сплиттер отодвигать и прятать, при повторном возвращать в было состояние, и фильтровать ивенты сплиттера на ручное его передвижение?

Основная проблема в том, что окно не масштабируется обратно, сплиттер здесь не поможет.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Октябрь 10, 2009, 06:18 »

Код:
void MyDialog::on_btnLeft_clicked( void )
{
QRect g = geometry();

if (frmRight->isVisible()) {
g.setWidth(width() - frmRight->width());
frmRight->setVisible(false);
btnLeft->setText("Show right");
}
else {
g.setWidth(width() + frmRight->width());
setMinimumWidth(minimumWidth());
frmRight->setVisible(true);
btnLeft->setText("Hide right");
}

setGeometry(g);
}
Записан
Marat(Qt)
Гость
« Ответ #8 : Октябрь 11, 2009, 15:02 »

Код:
void MyDialog::on_btnLeft_clicked()
{
  if(frmRight->isVisible()) {
    frmRight->setVisible(false);
    btnLeft->setText("Show right");
    loMain->setColumnStretch(1,0);
    QRect g = geometry();
    g.setWidth(m_old_width);
    setGeometry(g);
    adjustSize();
  }
  else {
    QRect g = geometry();
    m_old_width = g.width();
    loMain->setColumnStretch(1,1);
    frmRight->setVisible(true);
    btnLeft->setText("Hide right");
  }
}
Записан
CroCIV
Гость
« Ответ #9 : Октябрь 12, 2009, 08:20 »

решал такую проблему, два дня протра... пока не понял как оно устроено. Вощем простейший способ это скрываемую область сделать виджетом, несколько раз удостовериться в том что ни у одного из не скрываемых виджетов нет сайз политики на Экспандинг или Минимум экспандинг. Нельзя пользоваться распорками в данном случае горизонтальными, если распорки все же нужны, то их необходимо скрывать вместе со скрываемым виджетом, т.к. политика Фиксед не прокатывает их серавно распупыживает.
Если не поможет, значит подозреваю, что на главной форме используется компановка типа грид, верхняя ячейка которой какбэ объединена, в этом случае тоже должно работать но лучше начинать с простого, скомпануй по другому через доп лайоуты, если даже простейшая форма не работает как надо, то такого не бывает  Смеющийся
Но, если вдруг всетаки не работает, то всегда можно переопределить сайзхинт в данном случае у главного окна и управлять им каг душе угодно. В примере у меня какраз у тривьюхи переопределен сайзхинт, распупыживается по контенту или пока свободное место на не скрываемой части формы не кончится
Записан
Danila_Bagrofff
Гость
« Ответ #10 : Октябрь 12, 2009, 10:53 »

я однажды тоже долго мучался с QGridLayout и сложной компановкой с переменным количеством виджетов. В итоге компонвал обычными QVBoxLayout и QHBoxLayout. Все получилось более толково.
Записан
SLiDER
Гость
« Ответ #11 : Октябрь 12, 2009, 17:52 »

Выношу большую благодарность всем принявшим участие в обсуждении, особенно Igors и Marat(Qt). Оба последних предложенный варианта в большей или меньшей степени приблизились к требуемой функциональности, первый в большей, а второй в меньшей.
Первый вариант (пользователя Igors) правда тоже не был лишен недостатков, и при его использовании получались артефакты показанные на рисунке 1, а если установить минимальную ширину (таким образом: frmLeft->setMinimumWidth(frmLeft->sizeHint().width())) для левого виджета, о и такие как на рисунке 2.
Второй вариант (пользователя Marat(Qt)) не запоминал изменения геометрии внесенный пользователем и при скрытии правого виджета всегда принимал некий дефолтный размер, вероятно навязываемый ему лэйаутом, а при установке минимальной ширины (таким образом: frmLeft->setMinimumWidth(frmLeft->sizeHint().width())) для левого виджета, вообще переставал работать. Были еще какие-то неуловимые глюки связанные с масштабирование, но их очень долго описывать, а мне лень Улыбающийся.
Однако на базе материалов из данного треда, сегодня родился вариант, который меня удовлетворяет на все 100%, если не считать того что выглядит он не слишком изящно (некую похожую функциональность хотелось бы иметь прямо в библиотеке), однако вот он (для любопытствующих прикладываю и тестовый проект):

Код:
void MyDialog::on_btnLeft_clicked()
{
  QRect g = geometry();
  int left, top, right, bottom, spacing;
  loMain->getContentsMargins(&left, &top, &right, &bottom);
  spacing = loMain->spacing();
  if (frmRight->isVisible()) {
    g.setWidth(frmLeft->width()
                + spacing
                + left
                + right
                );
    setMinimumWidth(frmLeft->minimumWidth());
    setGeometry(g);
    frmRight->setVisible(false);
    btnLeft->setText("Show right");
  }
  else {
    g.setWidth( frmLeft->width()
               + frmRight->width()
               + spacing
               + left
               + right
               );
    setGeometry(g);
    setMinimumWidth( frmLeft->minimumWidth()
                   + frmRight->width()
                   + spacing
                   + left
                   + right
                   );
    frmRight->setVisible(true);
    btnLeft->setText("Hide right");
  }
}

P.S. При проведении экспериментов был обнаружен глюк в Qt. При создании и показе диалога, метод geometry() возвращает не валидные значения для координат x и y, а именно равные нулю, вне зависимости от того где он появляется. А если его передвинуть или отмасштабировать, то координаты возвращаются правильные.
« Последнее редактирование: Октябрь 12, 2009, 17:56 от SLiDER » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Октябрь 12, 2009, 18:43 »

Здравствуйте, SLiDER

1) Проверил Ваш вариант - у меня не работает (Qt 4.5.2). Окно сокращается при каждом show/hide. Кроме того после show ресайз становится ограничен - а об этом не просили.

2) Понятно что все spacing надо добавлять и размер самому вычислять но делать эту рутинную работу никому не хочется Улыбающийся  То что setGeometry не отрабатывает (без выкрутасов) ясно показывает - собака там порылась. Так что надо согласиться с тем что уже сказали - проще/практичнее избегать этого места.

Не разглядел артефакт на рисунке 1 (амбиций не имею просто интересно где  Улыбающийся)
Записан
SABROG
Гость
« Ответ #13 : Октябрь 12, 2009, 18:56 »

P.S. При проведении экспериментов был обнаружен глюк в Qt. При создании и показе диалога, метод geometry() возвращает не валидные значения для координат x и y, а именно равные нулю, вне зависимости от того где он появляется. А если его передвинуть или отмасштабировать, то координаты возвращаются правильные.

Сам ты глюк Улыбающийся Читай документацию про geometry. У тебя будут не валидные данные до тех пор пока не отработает цикл событий, а с ним и компановка виджетов через Layout'ы.
Записан
SLiDER
Гость
« Ответ #14 : Октябрь 12, 2009, 21:25 »

Здравствуйте, SLiDER

1) Проверил Ваш вариант - у меня не работает (Qt 4.5.2). Окно сокращается при каждом show/hide. Кроме того после show ресайз становится ограничен - а об этом не просили.

Эммм, вот сейчас не понял. Окно после show должно было растянуться на размер показанного виджета, а после hide ровно на его же размер и схлопнуться. У Вас мой пример не так работатет? А ресайз после показа правого виджета оганичен в меньшую сторону, что естественно, ибо определяется установленной миимальной шириной левого и правого виджетов, выставленной ручками.

2) Понятно что все spacing надо добавлять и размер самому вычислять но делать эту рутинную работу никому не хочется Улыбающийся  То что setGeometry не отрабатывает (без выкрутасов) ясно показывает - собака там порылась. Так что надо согласиться с тем что уже сказали - проще/практичнее избегать этого места.
Да все понятно Подмигивающий, просто примененая Вами конструкция - > setMinimumWidth(minimumWidth()) это вещь в себе особенно если до этого невыставить minimumWidth руками, ибо по умолчанию оно всегда будет равно нулю (покрайней мере в нашем примере), и единственное что оно делает ... а что вот собственно она делает ... нет, ну понятно, что выставляет некий минимальный размер для ширины виджета, однако все побочные действия не так уж и ясны, я сегодня полазил по исходникам Qt. Скажем там все весьма не тривиально  В замешательстве, одно можно сказать точно, что создается некий новый объект содержимое которого каким-то образом учитывается в последствии при вычислении размеров. И установка данного значения в ноль для нашего левого виджета вовсе не значит, что нам удасться схлопнуть его в ничто.

Не разглядел артефакт на рисунке 1 (амбиций не имею просто интересно где  Улыбающийся)
Дык, правый виджет же обрезан, т.е. окно отмасштабировалось, а он нет, и не должен был, но и кно недолжно.
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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