LINUX.ORG.RU

qt: компоновка, часть 2

 


0

3

Хочу такую штуку.
Есть прямоугольный QFrame (в ширину больше чем в высоту), туда пихаем круглый QDial. На QFrame вешаем горизонтальный лайаут в итоге диал автоматом растягивается на весь фрейм, а так как фрейм прямоугольный то по высоте диал как фрейм, а по ширине он отцентрирован. Все тянется и изменяется при изменении формы. Но вот хочется мне чтобы этот диал был не по центру (как по умолчанию), а был прижат вбок (например влево). При этом хочется чтобы диал при этом занимал все пространство по вертикали, а по горизонтали только смещался.
Перепробовал все варианты sizePolicy вместе со spacer, либо не работает, либо по вертикали не занимает все пространство.

cast EXL

★★★★★

The QSpacerItem class provides blank space in a layout.

AF ★★★
()

У QDial делаешь QSizePolicy( MinimumExpanding, MinimumExpanding) и все работает.

grondek
()
Ответ на: комментарий от grondek

и все работает.

Не работает, я такой вариант пробовал. диал сплющивается - по вертикали сверху и снизу куча места остается.

yax123 ★★★★★
() автор топика
Ответ на: комментарий от pS

Как правило если прилетает ссылка на букварь, то срыватель покровов, кроме как прочтения указанного букваря ничего не делал, причем даже руками не скомпелял, что в букваре написано. Вы лучше пришлите фрагмент ui-файла, где сделана правильная компоновка. А букварь я уже читал и утверждаю, что мой вопрос чуть сложней чем там описано.

yax123 ★★★★★
() автор топика
Ответ на: комментарий от yax123

Я же не просто так говорю, я проверил, оно действительно работает. Qt 4.8.x.

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Frame11</class>
 <widget class="QFrame" name="Frame11">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>734</width>
    <height>457</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Frame</string>
  </property>
  <property name="frameShape">
   <enum>QFrame::StyledPanel</enum>
  </property>
  <property name="frameShadow">
   <enum>QFrame::Raised</enum>
  </property>
  <layout class="QHBoxLayout" name="horizontalLayout">
   <item>
    <widget class="QDial" name="dial">
     <property name="sizePolicy">
      <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
    </widget>
   </item>
   <item>
    <spacer name="horizontalSpacer">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>351</width>
       <height>20</height>
      </size>
     </property>
    </spacer>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
grondek
()
Ответ на: комментарий от yax123

Очень хорошо! Просто думал: вдруг упустил чего?

pS
()
Ответ на: комментарий от grondek

Хотя... Он начинает нормально ресайзиться только с некоторого размера...

есть всего одно соотношение сторон где все нормально, в остальных случаях, диал становится меньше чем нужно. Для проверки сделайте форму квадратной, диал должен полностью вписаться, если не вписался, то решение неверное.

yax123 ★★★★★
() автор топика
Ответ на: комментарий от yax123

Вот я вижу, что начиная с некоторго размера у меня диал ресайзится правильно, а меньше - нифига... странно )

grondek
()

Задумался над задачей, придумал такой вариант:

Переопределяем QDial, чтобы его ширина никогда не превышала высоту.

#include "dial.h"

Dial::Dial(QWidget *parent) :
    QDial(parent)
{
    QSizePolicy hor( QSizePolicy::Maximum, QSizePolicy::MinimumExpanding );
    setSizePolicy( hor );

    setMaximumWidth( height() );
}

void Dial::resizeEvent(QResizeEvent *re)
{
    QDial::resizeEvent( re );

    setMaximumWidth( height() );
}

grondek
()
Ответ на: комментарий от grondek

А я так замутил: http://rghost.net/58505143

#include "Dial.h"

#include <QResizeEvent>

Dial::Dial(QWidget *parent) :
    QDial(parent)
{
}

void Dial::resizeEvent(QResizeEvent *evt)
{
    resize(evt->size().height(), evt->size().height());
}
EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 2)
Ответ на: комментарий от grondek

Так вроде бы нормально.

void Dial::resizeEvent(QResizeEvent *evt)
{
    if (parentWidget()->size().height() > parentWidget()->size().width()) {
        resize(evt->size());
    } else {
        resize(evt->size().height(), evt->size().height());
    }
}

А у меня твой пример не отрабатывает.

Для проверки сделайте форму квадратной, диал должен полностью вписаться, если не вписался, то решение неверное.

Вот этому не удовлетворяет. Хотя, возможно, не так готовлю. У тебя он через дизайнер проброшен? Если есть возможность, скинь проект.

EXL ★★★★★
()

У метода компоновщика addWidget() есть опция выравнивания. Т. е. у тебя будет что-то типа «layout->addWidget(dial, 0, Qt::AlignLeft)»

anonymous
()
Ответ на: комментарий от anonymous

Вот такого ответа я и ждал. Хотя товарисчь с ссылками в целом тоже верно указал - по второй ссылке было упоминание. С другой стороны сильно лучше от этого не стало. диал конечно прижимается вбок, но при этом все равно сплющивается. Такое ощущение, что реализация выравнивания сделана через добавление Stretch. Но самое забавное то что, если вместо диала воткнуть самодельный виджет на базе QWidget, он вообще не отрисовывается.

yax123 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Проблема же похоже не в том, что в LayoutItem'е диал не туда прижимается, а в том, что он странно масштабируется.

grondek
()
Ответ на: комментарий от grondek

Согласен, решение рабочее, но исправлять размеры в resizeEvent(QResizeEvent *re) на мой взгляд жуткий костыль. Мое чувство прекрасного противится такому. Правильный вариант это Qt::AlignLeft, но похоже он работает криво. Или вообще у разрабов qt тема компоновки еще требует детальной проработки.

yax123 ★★★★★
() автор топика
Ответ на: комментарий от grondek

А если так?

QDial *dial = new QDial(this);

QHBoxLayout *intLayout = new QHBoxLayout();
intLayout->addWidget(dial);

QWidget *wgt = new QWidget(this);
wgt->setLayout(intLayout);

QHBoxLayout *outLayout = new QHBoxLayout();
outLayout->addWidget(wgt, 0, Qt::AlignLeft);

QFrame *frame = new QFrame(this);
frame->setLayout(outLayout);

Только, ясное дело, указателями

anonymous
()
Ответ на: комментарий от anonymous

s/Только, ясное дело, указателями//

Просто изначально не указателями сделал, забыл удалить

anonymous
()
Ответ на: комментарий от anonymous

А если так?

Неа, те же яйца, только в профиль.

щас попробовал вместо dial воткнуть QCalendarWidget. И похоже меня осенило. В куте нет такого понятие как пропорциональность сторон, круглый виджет это просто прямоугольник в который вписывают круг. И всем пофиг, что для круглых виджетов предпочитаемая форма квадратная. Календарь у меня просто уродливо вытянулся в по вертикали. Хотя для календаря тоже идеальная форма ближе к квадрату. Как мне кажется, такие виджеты не очень предназначены для автоматической компоновки (их нужно все пружинами подпирать со всех сторон). А для нормальной компоновки нужно вводит еще один параметр с указанием к каким пропорциям должен «тяготеть» виджет.

yax123 ★★★★★
() автор топика
Ответ на: комментарий от yax123

куте

Кьют, блджад!

нет такого понятие как пропорциональность сторон, круглый виджет это просто прямоугольник в который вписывают круг

Не совсем. Есть такая штука, как sizeHint(), который сообщает желательные размеры. Если у тебя где-нибудь назначается sizePolicy, то отмени. По-хорошему, у тебя не должно быть искажений, виджеты вместо этого должны обрезаться (и не будут давать уменьшить размеры меньше minimalSize()). У меня как-то было, что оно искажалось, но я, если честно, уже не помню, из-за чего. Покажи код функции, добавляющей dial, может, вспомню.

Почему тут нельзя оставить коммент анонимно, но не разлогиниваясь? Надоело каждый раз кнопку жать

anonymous
()
Ответ на: комментарий от anonymous

Делаю крайне просто:

ik = new Ik(this);
hboxLayout = new QHBoxLayout(ui->frame);
hboxLayout->addWidget(ik,1);

Есть такая штука, как sizeHint(),

дык она задает размер, причем жестко. Ну может можно чуток поправить при помощи sizePolicy. А нужно не жесткий размер, а желаемое соотношение сторон, чтобы по возможности виджет становился более квадратным либо вытянутым.


Кьют, блджад!
Да в курсе я, язык сломаешь пока это вышепчешь, куте легче и благозвучней. Кому режет слух и мозг, пусть пустырничка примут.

yax123 ★★★★★
() автор топика
Последнее исправление: yax123 (всего исправлений: 1)
Ответ на: комментарий от yax123

Ik

Наследник от QDial? Какие-нибудь методы были переопределены?

дык она задает размер

/Рекомендуемый/ размер. Т. е. я могу как угодно менять размеры окна — оно будет подстраиваться. У меня вот так всё работает, как надо, разве что падает при закрытии (т. к. надо было через указатели всё делать), никаких искажений в какую-либо сторону нет:

QApplication app(argc, argv);

QDial dial;
QHBoxLayout layout;
layout.addWidget(&dial, 0, Qt::AlignLeft);
QFrame frame;
frame.setLayout(&layout);
frame.show();

return app.exec();

язык сломаешь пока это вышепчешь

Не имею с этим проблем

anonymous
()
Ответ на: комментарий от anonymous

Наследник от QDial?

неа, от Qwidget просто тоже свой круглы виджет с переопределенным paintEvent. а там уже рисую круглое и желтое.

Т. е. я могу как угодно менять размеры окна — оно будет подстраиваться.

то есть, если поставить sizehint = (100,100), а окно сделать 1000 на 1800, оно само растянется до 1000*1000?

Не имею с этим проблем

это я не имею. А вот с тобой что-то не так :)

, блджад!

yax123 ★★★★★
() автор топика
Ответ на: комментарий от yax123

то есть, если поставить sizehint = (100,100), а окно сделать 1000 на 1800, оно само растянется до 1000*1000?

ЕМНИП, да. Я же привёл пример с QDial-ом — там такой же принцип.

, блджад!

http://lurkmore.to/Блджад // Оффтоп, всё же

anonymous
()
Ответ на: комментарий от anonymous

Забавно. если так добавить:

 hboxLayout->addWidget(ik,0, Qt::AlignLeft);
то событие для отрисовки не вызывается вообще.
а если так:

 hboxLayout->addWidget(ik,0);

то все нормально отрисовывается. похоже еще чуть-чуть и придется лезть в исходный код и смотреть чего-там навертели.

yax123 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.