Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: n4ela от Декабря 13, 2009, 17:24



Название: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: n4ela от Декабря 13, 2009, 17:24
Есть главное окно, на нем центральный виджет на котором vertical layout и в нем мой виджет, в конструкторе моего widget'a вызывывается метод restart и в нем я должен получить ширину и высоту виджета, но данные получаются не правильные, хотя в методе paintEvent высота и ширина уже правильные.

Я так понял что мой метод начинает отрабатываться до отрисовки окна, и из-за этого размер получается не правильный.
Вот и вопрос как можно получать верные данные, где мне можно начинать вызывать мои методы, что бы окно уже было отрисовано?

И еще маленький вопрос о инклудах.
Как лучше лучше писать:
#include <QtGui>
#include <QtCore>
class ...;
class ...;
class ...;

или
#include <QClass...>
#include <QClass...>
#include <QClass...>

Тролли вроде рекомендуют по первому способу, но дизайнер генерирует код по второму варианту. В чем разница?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: lit-uriy от Декабря 13, 2009, 17:38
Подумай над такой темой:
находясь в конструкторе объекта, объект уже сконструирован? Т.е. его размеры уже обсчитаны и известны?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: lit-uriy от Декабря 13, 2009, 17:39
>>И еще маленький вопрос о инклудах.
смешиваешь разные темы в одну, да и вопрос такой уже был (см. forward declaration)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 18:02
Подумай над такой темой:
находясь в конструкторе объекта, объект уже сконструирован? Т.е. его размеры уже обсчитаны и известны?

Да - сконсруирован уже в начале конструктора. A проблема в том что нет метода пересчета или подсчета размеров.
И вообще, с конструктором не связано, общая кривизна системы Layouts у QT. До N отрисовки после последовательности ресайзов не возможно гарантировать правильное получение каких-либо размеров.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: lit-uriy от Декабря 13, 2009, 18:38
>>Да - сконсруирован уже в начале конструктора.
В начале конструктора сконструирован только базовый класс, то что память выделилась, ещё ни о чём не говорить, там кроме мусора ещё ничего нет

>>И вообще, с конструктором не связано,
Как это не связано, пока конструктор не завершился, объект не сконструирован.
Нет ни одного размера, т.к. компоновщик ещё не вызывал методы (ещё не существующего виджета) для получения/управления размерами


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: Igors от Декабря 13, 2009, 19:10
>>Да - сконсруирован уже в начале конструктора.
В начале конструктора сконструирован только базовый класс, то что память выделилась, ещё ни о чём не говорить, там кроме мусора ещё ничего нет
Не только члены и базовые классы - сам экземпляр инициализирован, указатель на VMT прописан, виртуальные методы в конструкторе вызывать можно.

Размеров в конструкторе не получить - это правильно поскольку размеры зависят от (многих) парентов и лайаутов. Но плохо что их вообще нельзя получить до show и часто приходится заниматься неприятными вычислениями длин/ширин или полагаться на мудрость лайаутов.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 19:28
Насколько я помню если выбросить исключение в конструкторе, то объект создан не будет, однако нет гарантии того, что выделенная память будет освобождена, это зависит от компилятора не смотря на то, что комитет ISO/ANSI по С++ считает, что память должна освобождаться неявно. Но это не означает, что проблема в конструкторе как таковая. Дело в системе событий. Все методы по отрисовке и установки размеров виджета начинают выполняться как реакция на события типа QEvent::Resize, QEvent::Paint. Пока главный цикл не запущен (return app.exec()) эти события ждут своего часа в очереди. Компановщики (layouts) также являются генераторами подобных событий. Поэтому свой метод по получению размера виджета нужно вызывать последним. Это можно сделать после вызова qApp->processEvents() или через вызов слота по QTimer::singleShot(), сигнал которого будет поставлен в конец очереди.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 19:38
Не только члены и базовые классы - сам экземпляр инициализирован, указатель на VMT прописан, виртуальные методы в конструкторе вызывать можно.
+10
Маленькое уточнение. Виртуальные методы в конструкторе вызывать можно, но не как виртуальные, поскольку в C++ конструкторы не виртуальны, на мой взгляд один из самых больших недостатков C++, - постоянно приходится делать init методы. :(

Размеров в конструкторе не получить - это правильно поскольку размеры зависят от (многих) парентов и лайаутов.

Абсолютно не согласен что - правильно.
Достаточно в QT сделать метод типа "calculateSize" возвращающий размеры для уже сконструированного контекста. Естественно, что добавление новых элементов и/или их переинициализация после вызова "calculateSize" могут привести к неактуальности полученного размера, но точно так же происходит и после "show"(если были изменнения в системе визуальных объектов). Короче, не вижу разницы когда можно вычислять размеры, в конструкторе(в нужном с точки зрения программера месте) или после.



Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 19:50
Насколько я помню если выбросить исключение в конструкторе, то объект создан не будет, однако нет гарантии того, что выделенная память будет освобождена, это зависит от компилятора не смотря на то, что комитет ISO/ANSI по С++ считает, что память должна освобождаться неявно.

Ооо....
Всегда считал что при исключении в конструкторе память под объект должна освобождаться неявно(за исключением создаваемых в конструкторе объектов в куче), поскольку нет способа в C++ после исключения в конструкторе объекта освободить выделенную под него память явно!

Но это не означает, что проблема в конструкторе как таковая. Дело в системе событий. Все методы по отрисовке и установки размеров виджета начинают выполняться как реакция на события типа QEvent::Resize, QEvent::Paint. Пока главный цикл не запущен (return app.exec()) эти события ждут своего часа в очереди. Компановщики (layouts) также являются генераторами подобных событий. Поэтому свой метод по получению размера виджета нужно вызывать последним. Это можно сделать после вызова qApp->processEvents() или через вызов слота по QTimer::singleShot(), сигнал которого будет поставлен в конец очереди.

А как насчет adjustSize вызываемого в конструкторе? И получения размеров после него, как правило корректных.
Так что считаю что проблема надумана троллями.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: Igors от Декабря 13, 2009, 20:26
Маленькое уточнение. Виртуальные методы в конструкторе вызывать можно, но не как виртуальные, поскольку в C++ конструкторы не виртуальны, на мой взгляд один из самых больших недостатков C++, - постоянно приходится делать init методы. :(
:) Конструктор не может быть виртуальным поскольку именно его вызов прописывает VMT. А также лучше сказать: при конструировании базового класса будут вызываться его виртуальные методы (а не виртуальные методы порожденного класса).

Короче, не вижу разницы когда можно вычислять размеры, в конструкторе(в нужном с точки зрения программера месте) или после.
По-моему нужен метод виджета который бы обеспечивал "все размеры посчитаны, больше меняться не будут" (чтобы не приходилось делать это коряво через таймер). Может такой и есть но я его не нашел. Пробовал resize, setGeometry (для главного окна конечно) - не бычит, размеров child виджетов я не имею :'(  

Edit:
А как насчет adjustSize вызываемого в конструкторе? И получения размеров после него, как правило корректных.
А как "не правило"? :) Я пробовал и иногда adjustSize работает, иногда нет. Как я понял зависит от флагов (Fixed, Expanded) - тоже не дело


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 20:43
А как насчет adjustSize вызываемого в конструкторе?

Если это работает, то это еще один способ обхода проблемы. А проблема не надумана троллями, просто она есть и люди всё продолжают и продолжают создавать подобные темы. В документации я не нашел об этом упоминания.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 20:45
Камрады, что то я не соображу с размерами...
Вот типичный код:
Код
C++ (Qt)
{
QVBoxLayout *layout = new QVBoxLayout( this );
 
QTextEdit *edit = new QTextEdit( this );
layout->addWidget( edit );
 
QLabel *label = new QLabel( this );
layout->addWidget( label );
 
...
}
 
Какой размер должен быть известен в конструкторе объекта edit, когда при его конструировании еще не известно в какой layout он будет помещен (и будет ли вообще), сколько еще виджетов будет в этом layout'е? Кто сможет это посчитать?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 20:47
Маленькое уточнение. Виртуальные методы в конструкторе вызывать можно, но не как виртуальные, поскольку в C++ конструкторы не виртуальны, на мой взгляд один из самых больших недостатков C++, - постоянно приходится делать init методы. :(
:) Конструктор не может быть виртуальным поскольку именно его вызов прописывает VMT. А также лучше сказать: при конструировании базового класса будут вызываться его виртуальные методы (а не виртуальные методы порожденного класса).

Именно это и называется виртуальным конструктором, т.е. когда вызовы виртуальных методов внутри него виртуальны(а не вызовы методов базового класса). Пример подобного - Delphi.

Код
C++ (Qt)
class BaseClass {
public:
 int X;
public:
 BaseClass () {init();}
 virtual init() {X=0;}
};
 
class ChildClass: public BaseClass {
public:
 ChildClass () {}
 virtual init() {X=111;}
};
 
{
  BaseClass Base;
  ChildClass Child;
}
 

// В С++
//  Base.X == 0;
//  Child.X == 0;

// В Delphi (не учитывая синтаксис)
//  Base.X == 0;
//  Child.X == 111;

По-моему нужен метод виджета который бы обеспечивал "все размеры посчитаны, больше меняться не будут" (чтобы не приходилось делать это коряво через таймер). Может такой и есть но я его не нашел. Пробовал resize, setGeometry (для главного окна конечно) - не бычит, размеров child виджетов я не имею :'( 

"все размеры посчитаны, больше меняться не будут" - поскольку можно в любой момент изменить структуру объектов.
А вот получениее размеров для текущего момента(для текущей структуры объектов) просто необходимо ("calculateSize" )


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 20:50
Кто сможет это посчитать?

Как я и писал в конце метода вызывать qApp->processEvents() и получать после него или ставить в очередь вызов слота (Qt::QueuedConnection). Естественно, что размеры виджета могут тут же поменяться на другие после того как они уже были получены, просто нужно дополнять документацию, чтобы народ не удивлялся.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 20:57
Камрады, что то я не соображу с размерами...
Вот типичный код:
Код
C++ (Qt)
...
Какой размер должен быть известен в конструкторе объекта edit, когда при его конструировании еще не известно в какой layout он будет помещен (и будет ли вообще), сколько еще виджетов будет в этом layout'е? Кто сможет это посчитать?

По-умолчанию для текущего фонта, текущего текста, текущих ограничений на размер, итд...


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: Igors от Декабря 13, 2009, 20:57
Как я и писал в конце метода вызывать qApp->processEvents() и получать после него или ставить в очередь вызов слота (Qt::QueuedConnection). Естественно, что размеры виджета могут тут же поменяться на другие после того как они уже были получены, просто нужно дополнять документацию, чтобы народ не удивлялся.
processEvents и экран обновит и много чего может еще сделать что к размерам не имеет отношения. Коряво, хотя согласен - лучшего не видно (в текущей версии)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:00
По-умолчанию для текущего фонта, текущего текста, текущих ограничений на размер, итд...
А для чего нужен этот размер, если он тут-же измениться компоновщиком?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: Igors от Декабря 13, 2009, 21:07
А для чего нужен этот размер, если он тут-же измениться компоновщиком?
То уже я возьму на себя. Было бы замечательно если перед вызовом mainWindow->show() я мог бы вызвать что-то типа mainWindow->adjustSize() и получить все размеры как они будут на экране


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:07
Как я и писал в конце метода вызывать qApp->processEvents() и получать после него или ставить в очередь вызов слота (Qt::QueuedConnection). Естественно, что размеры виджета могут тут же поменяться на другие после того как они уже были получены, просто нужно дополнять документацию, чтобы народ не удивлялся.

Никак не решает проблему если необходимо узнать размеры в конструкторе.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:10
То уже я возьму на себя. Было бы замечательно если перед вызовом mainWindow->show() я мог бы вызвать что-то типа mainWindow->adjustSize() и получить все размеры как они будут на экране
Это уже получение размера не в конструкторе, не?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:13
По-умолчанию для текущего фонта, текущего текста, текущих ограничений на размер, итд...
А для чего нужен этот размер, если он тут-же измениться компоновщиком?

Для описанного тобой примера - смысла мало.
А вот получение размеров элементов в конце конструктора окна очень даже важно:
MyWindow::MyWindow () {
...
...
calculateSize();

// get children sizes

}

И в любой другой момент если необходимо


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:15
То уже я возьму на себя. Было бы замечательно если перед вызовом mainWindow->show() я мог бы вызвать что-то типа mainWindow->adjustSize() и получить все размеры как они будут на экране
А откуда adjustSize узнает что ты будешь вызывать именно show(), а не showFullScreen() или showMaximized()?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:25
Кстати в текущей концепции QT, со всем этим связана очень большая кривизна - невозможно получить размеры для виджетов которые еще не были визуализированы, т.е. которые не были isVisible()!

Пример того что меня уже достало:
Не устанавливаются правильные размеры QTableWidget - пока не перещелкнешь все закладки, и обязательно после его визуализации, и обязательно через processEvents()


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:31
Код
C++ (Qt)
QVBoxLayout *layout = new QVBoxLayout( this );
 
QTextEdit *textEdit = new QTextEdit( this );
layout->addWidget( textEdit );
 
setLayout( layout );
 
resize( 200, 200 );
 
qDebug() << textEdit->size();
 
layout->activate();
 
qDebug() << textEdit->size();
 
Цитировать
QSize(100, 30)
QSize(178, 178)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:33
Пример того что меня уже достало:
Не устанавливаются правильные размеры QTableWidget - пока не перещелкнешь все закладки, и обязательно после его визуализации, и обязательно через processEvents()

Поясняю:
Имеем диалог с закладками. Задача сделать фиксированный минимальный размер этого диалога.
Задача не решаема - зависит от выбранной закладки. Если изначально была выбрана закладка с суммарно меньшим возможным размером элементов, то при переключении пользователем на закладку с суммарно большим размером элементов - диалог изменит размеры.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:36
Извиняюсь не QTableWidget, а QTabWidget.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:38
Поясняю:
Имеем диалог с закладками. Задача сделать фиксированный минимальный размер этого диалога.
Задача не решаема - зависит от выбранной закладки. Если изначально была выбрана закладка с суммарно меньшим возможным размером элементов, то при переключении пользователем на закладку с суммарно большим размером элементов - диалог изменит размеры.
Это да, такая же фигня и у меня, тут только с большим бубном...  ;D


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: Igors от Декабря 13, 2009, 21:45
А откуда adjustSize узнает что ты будешь вызывать именно show(), а не showFullScreen() или showMaximized()?
А мне не нужно "на все случаи" - пусть сделает для размеров установленных setSize. А когда у меня получившиеся размеры будут на руках я задам кому надо setMinimumSize/setMaximumSize а остальное пусть лайауты занимаются. Так ведь нет такой возможности  :'(


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:46
Код
C++ (Qt)
QVBoxLayout *layout = new QVBoxLayout( this );
 
QTextEdit *textEdit = new QTextEdit( this );
layout->addWidget( textEdit );
 
setLayout( layout );
 
resize( 200, 200 );
 
qDebug() << textEdit->size();
 
layout->activate();
 
qDebug() << textEdit->size();
 
Цитировать
QSize(100, 30)
QSize(178, 178)

Ну и все нормально.
А теперь вызываем this->calculateSize(); и получаем для textEdit правильные размеры, актуальные пока у окна(this) чего-то не добавили/изменили


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:48
Тогда все нормально, все что хотели получаем?  :)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:48
А откуда adjustSize узнает что ты будешь вызывать именно show(), а не showFullScreen() или showMaximized()?
А мне не нужно "на все случаи" - пусть сделает для размеров установленных setSize. А когда у меня получившиеся размеры будут на руках я задам кому надо setMinimumSize/setMaximumSize а остальное пусть лайауты занимаются. Так ведь нет такой возможности  :'(

Не получится.  :( Задача в общем случае неразрешима. Но разрешима для текущего состояния.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 21:48
Кстати так тоже вполне работает...:

Код
C++ (Qt)
Widget::Widget(QWidget *parent) :
   QWidget(parent),
   ui(new Ui::Widget)
{
   ui->setupUi(this);
 
   qDebug() << ui->groupBox->geometry() << ui->listView->geometry() << ui->pushButton->geometry();
   show();
   qDebug() << ui->groupBox->geometry() << ui->listView->geometry() << ui->pushButton->geometry();
}
 

Код:
QRect(0,0 100x30) QRect(0,0 100x30) QRect(0,0 100x30)
QRect(11,216 324x13) QRect(92,11 243x199) QRect(11,99 75x23)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:50
Тогда все нормально, все что хотели получаем?  :)

Так нет подобного метода "calculateSize"! Надо чтоб тролли его еще сделали.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:52
Так нет подобного метода "calculateSize"! Надо чтоб тролли его еще сделали.
Подожди, мы в конструкторе можем получить размеры и положения всех дочерних виджетов, или какой размер хотим получить?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 21:53
Кстати так тоже вполне работает...:

Код
C++ (Qt)
...

Код:
QRect(0,0 100x30) QRect(0,0 100x30) QRect(0,0 100x30)
QRect(11,216 324x13) QRect(92,11 243x199) QRect(11,99 75x23)

Ужасс.. :)
show прямо в конструкторе, прикольно. Не пробовал.
Но задача определить размеры до show!


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 21:59
Код
C++ (Qt)
QVBoxLayout *layout = new QVBoxLayout( this );
 
QLabel *label = new QLabel( tr( "Label" ), this );
layout->addWidget( label );
 
QTextEdit *textEdit = new QTextEdit( this );
textEdit->setMinimumSize( 400, 400 );
layout->addWidget( textEdit );
 
setLayout( layout );
 
qDebug() << minimumSize();
qDebug() << layout->activate();
qDebug() << minimumSize();
 

Виджет будет создан (если он не будут помещен в другой layout) размером minimumSize().


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:06
Так нет подобного метода "calculateSize"! Надо чтоб тролли его еще сделали.
Подожди, мы в конструкторе можем получить размеры и положения всех дочерних виджетов, или какой размер хотим получить?

Не совсем так. Попытаюсь описать концепцию:
Главное - не важно когда и где(в конструкторое ли позже) мы хотим определить размеры. Важна текущая компоновка и состояние(может зависит от данных) визуальных объектов.
Теперь:
1) calculateSize - расчитывает размеры this в зависимости от текущего состояния и компоновки дочерних элементов
2) calculateSize для элемента(не окна) расчитывает его текущие размеры в зависимости от размеров его "главного" родителя(окна). При необходимости calculateSize дочернего элемента делает вызов calculateSize "главного" родителя


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 22:10
Не совсем так. Попытаюсь описать концепцию:
Главное - не важно когда и где(в конструкторое ли позже) мы хотим определить размеры. Важна текущая компоновка и состояние(может зависит от данных) визуальных объектов.
Теперь:
1) calculateSize - расчитывает размеры this в зависимости от текущего состояния и компоновки дочерних элементов
2) calculateSize для элемента(не окна) расчитывает его текущие размеры в зависимости от размеров его "главного" родителя(окна). При необходимости calculateSize дочернего элемента делает вызов calculateSize "главного" родителя
Смотри выше, это возвращает minimumSize().

Код
C++ (Qt)
MainWindow::MainWindow()
: QWidget( 0 )
{
QVBoxLayout *layout = new QVBoxLayout( this );
 
QLabel *label = new QLabel( tr( "Label" ), this );
layout->addWidget( label );
 
QTextEdit *textEdit = new QTextEdit( this );
textEdit->setMinimumSize( 400, 400 );
layout->addWidget( textEdit );
 
setLayout( layout );
 
qDebug() << layout->activate();
qDebug() << minimumSize(); // Печатаем размер виджета
}
 
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow *mw = new MainWindow();
mw->show();
qDebug() << mw->size(); // Проверяем после show
return app.exec();
}
 
Цитировать
QSize(422, 444)
QSize(422, 444)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 22:13
3 варианта показывают одни и те же результаты:

  • show();
  • QTimer::singleShot(0, this, SLOT(myslot()));
  • layout()->activate();

Первый может показаться не логичным и громоздким, а также не соответствовать логике приложения, если пользователь не собирается показывать окно, а скрывать его повторно накладно. Второй сложен и не соответствует требованию определить размеры или координаты виджета внутри конструктора. Третий не работает для простых виджетов, где просто может не быть компановщиков, однако в этом случае координаты и размеры у меня возвращаются без проблем и лишних телодвижений. Полагаю, что наличие компановщика заставляет Qt "затирать" размеры и координаты виджетов.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:17
Не совсем так. Попытаюсь описать концепцию:
Главное - не важно когда и где(в конструкторое ли позже) мы хотим определить размеры. Важна текущая компоновка и состояние(может зависит от данных) визуальных объектов.
Теперь:
1) calculateSize - расчитывает размеры this в зависимости от текущего состояния и компоновки дочерних элементов
2) calculateSize для элемента(не окна) расчитывает его текущие размеры в зависимости от размеров его "главного" родителя(окна). При необходимости calculateSize дочернего элемента делает вызов calculateSize "главного" родителя
Смотри выше, это возвращает minimumSize().

Ну если бы все было так просто, то не было бы у нас проблем с тем же QTabWidget.
И причем здесь minimumSize. Интересуют размеры/положение объекотв на текущий момент такие, какие были бы если бы мы их начали визуализировать(show) в данный момент, в данном состоянии.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:20
3 варианта показывают одни и те же результаты:

  • show();
  • QTimer::singleShot(0, this, SLOT(myslot()));
  • layout()->activate();

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

Для приведенного мной примера с QTabWidget - не поможет.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 22:22
Ну если бы все было так просто, то не было бы у нас проблем с тем же QTabWidget.
И причем здесь minimumSize. Интересуют размеры/положение объекотв на текущий момент такие, какие были бы если бы мы их начали визуализировать(show) в данный момент, в данном состоянии.
Не пойму что еще не устраивает?
В конструкторе виджета мы получаем размер, который он будет иметь после show() - смотрим minimumSize().
Геометрию дочерних виджетов так же получаем - смотрим geometry().


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 22:23
Для приведенного мной примера с QTabWidget - не поможет.
Не поможет, потому что размер главного виджета будет подобран в соответствии с minimumSize первой видимой страницы.
Но вроде хотели размеры в конструкторе получить, не?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 22:26
При переключении вкладок должны меняться размеры главного окна, правильно? Т.е. логика как здесь: http://crossplatform.ru/node/242


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:29
Ну если бы все было так просто, то не было бы у нас проблем с тем же QTabWidget.
И причем здесь minimumSize. Интересуют размеры/положение объекотв на текущий момент такие, какие были бы если бы мы их начали визуализировать(show) в данный момент, в данном состоянии.
Не пойму что еще не устраивает?
В конструкторе виджета мы получаем размер, который он будет иметь после show() - смотрим minimumSize().
Геометрию дочерних виджетов так же получаем - смотрим geometry().

Я не понял, как ты хочешь получить эти размеры(точно такие, какие будут после show() ) ??


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 22:31
Я не понял, как ты хочешь получить эти размеры(точно такие, какие будут после show() ) ??
Код
C++ (Qt)
MainWindow::MainWindow()
       : QWidget( 0 )
{
       QVBoxLayout *layout = new QVBoxLayout( this );
 
       QLabel *label = new QLabel( tr( "Label" ), this );
       layout->addWidget( label );
 
       QTextEdit *textEdit = new QTextEdit( this );
       textEdit->setMinimumSize( 400, 400 );
       layout->addWidget( textEdit );
 
       setLayout( layout );
 
       qDebug() << layout->activate();
       qDebug() << minimumSize(); // Размер виджета, который будет после show
 
qDebug() << textEdit->geometry(); // Геометрия дочернего виджета textEdit, которая будет после show
}
 


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:37
При переключении вкладок должны меняться размеры главного окна, правильно? Т.е. логика как здесь: http://crossplatform.ru/node/242

Задача как раз обратная!
1) Диалог с закладками не должен менять размеры при переключении закладок(пока не поменяли компоновку и сосояние элементов)!
2) Его размеры должны определятся размерами максимальной ширины и высоты из всех закладок.

Это и есть типичная задача:
Сделали диалог с закладками, выбрали любую по-умочанию, сделали диалогу adjustSize и зафиксировали его размер, и не паримся что при перещелкивании закладок он его изменит.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 13, 2009, 22:40
Задача как раз обратная!
1) Диалог с закладками не должен менять размеры при переключении закладок(пока не поменяли компоновку и сосояние элементов)!
2) Его размеры должны определятся размерами максимальной ширины и высоты из всех закладок.

Это и есть типичная задача:
Сделали диалог с закладками, выбрали любую по-умочанию, сделали диалогу adjustSize и зафиксировали его размер, и не паримся что при перещелкивании закладок он его изменит.
Цитировать
По умолчанию, QTabWidget::minimumSizeHint() возвращает максимальный размер всех существующих страниц, а не только видимой страницы.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 22:45
Диалог с закладками не должен менять размеры при переключении закладок(пока не поменяли компоновку и сосояние элементов)!

сделали диалогу adjustSize и зафиксировали его размер, и не паримся что при перещелкивании закладок он его изменит.

Получается, если в выбраной вкладке по умолчанию количество элементов по высоте и/или ширине будет меньше чем в скрытых вкладках и мы сделаем adjustSize(), что (наверно) должно уменьшить размер окна, далее зафиксируем этот размер (setFixedSize()?), то при переключении на вкладку, где размеры элементов занимают большую площадь, все виджеты должны свернуться в трубочку, чтобы влезать в маленькое главное окошко или уползти за пределы виджета куда-то вбок или вниз до такой степени, что пользователю понадобится скроллбар. На примере компилируемых исходных кодов и картинок как должно быть (до и после) можешь показать чего ты хочешь?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:52
По умолчанию, QTabWidget::minimumSizeHint() возвращает максимальный размер всех существующих страниц, а не только видимой страницы.

Попробую


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:54
Я не понял, как ты хочешь получить эти размеры(точно такие, какие будут после show() ) ??
Код
C++ (Qt)
...

Ладно, на сегодня отваливаюсь, пора спать. :)
Завтра напишу тест и попробую подтвердить или опровергнуть предложеный тобой вариант. Если не прокатит, то выложу, поробуешь решить задачу для теста.
 


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 13, 2009, 22:56
Диалог с закладками не должен менять размеры при переключении закладок(пока не поменяли компоновку и сосояние элементов)!

сделали диалогу adjustSize и зафиксировали его размер, и не паримся что при перещелкивании закладок он его изменит.

Получается, если в выбраной вкладке по умолчанию количество элементов по высоте и/или ширине будет меньше чем в скрытых вкладках и мы сделаем adjustSize(), что (наверно) должно уменьшить размер окна, далее зафиксируем этот размер (setFixedSize()?), то при переключении на вкладку, где размеры элементов занимают большую площадь, все виджеты должны свернуться в трубочку, чтобы влезать в маленькое главное окошко или уползти за пределы виджета куда-то вбок или вниз до такой степени, что пользователю понадобится скроллбар. На примере компилируемых исходных кодов и картинок как должно быть (до и после) можешь показать чего ты хочешь?

Скроллбар не появится. Диалог расширится если минимальный требуемый размер для страницы больше текущего.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 13, 2009, 23:25
Скроллбар не появится. Диалог расширится если минимальный требуемый размер для страницы больше текущего.

Естественно. Непонятно только зачем ограничивать размер окна настолько, чтобы виджеты не могли бы умещаться даже в свои минимальные размеры, ведь по тому, что я прочитал ты хочешь именно этого.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 07:42
Непонятно только зачем ограничивать размер окна настолько, чтобы виджеты не могли бы умещаться даже в свои минимальные размеры, ведь по тому, что я прочитал ты хочешь именно этого.

Нет, ты меня не понял. :(
Задача сделать диалог с фиксированным размером, пользователь не может менять размер диалога.
Размер диалога должен программно установиться  так, чтобы:
- Все элементы были достаточных размеров - не имели скроллеров, итд.
И
- Был минимально возможных размеров
И
- Не изменял размеров при переключении закладок





Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 08:23
Вот сделал простой тест.
Задача заставить диалог иметь фиксированный минимально необходимый размер так, чтобы не было изменений его размеров при переключении закладок!
Расположение закладок не менять.
Закладку выбранную по-умочанию не менять.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 14, 2009, 09:39
Посмотри, у меня вроде делает так как ты хочешь.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 09:52
Посмотри, у меня вроде делает так как ты хочешь.

Нет, не работает. Не принимает манимально необходимый размер.

На картинке bad-size.png - размер что получилося у тебя
На картинке good-size.png - размер который должен быть


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 14, 2009, 09:54
Нет, не работает. Не принимает манимально необходимый размер.
А ты мой файл dialog_options.ui используешь?  ;)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 09:55
Сделай так:
Код
C++ (Qt)
TDialogOptions::TDialogOptions(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
ui.setupUi(this);
   setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
 
   adjustSize();
   setMaximumSize(geometry().size());
}
 

Потом запусти, перключись на первую закладку и увидишь тот размер который должен быть при первом запуске диалога(с выбраной второй закладкой)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 09:55
Нет, не работает. Не принимает манимально необходимый размер.
А ты мой файл dialog_options.ui используешь?  ;)

Да, полностью твой проект.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 09:56
По умолчанию, QTabWidget::minimumSizeHint() возвращает максимальный размер всех существующих страниц, а не только видимой страницы.

Несмотря на то, что так написано - так не происходит. Возвращает минимальный размер только видимой вкладки, никакие layout()->activate() этому не способствуют.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:05
Еще один прикол. Если для такого варианта:

Код
C++ (Qt)
TDialogOptions::TDialogOptions(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
ui.setupUi(this);
   setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
 
   adjustSize();
   setMaximumSize(geometry().size());
}

переставить в дизайнере местами закладки, "View/Console" -  первая, и выбрать по-умолчанию "View/Console", то работает корректно.
Вообще фигня какая-то!


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 14, 2009, 10:07
Да, полностью твой проект.
Странно, у меня все нормально.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:12
Да, полностью твой проект.
Странно, у меня все нормально.

О..., Оно еще и под разными опреционками по-разному работает!
У меня XP.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 10:13
Я так понимаю задача сводится к такой:
- имеем произвольный размер диалога, который может быть заведомо больше или меньше размера, который бы установил adjustSize() при показе вкладки с самыми большими размерами
- нужно получить эти размеры и установить новый размер всему диалогу


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:17
Я так понимаю задача сводится к такой:
- имеем произвольный размер диалога, который может быть заведомо больше или меньше размера, который бы установил adjustSize() при показе вкладки с самыми большими размерами
- нужно получить эти размеры и установить новый размер всему диалогу

Можно и так описать.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 14, 2009, 10:17
О..., Оно еще и под разными опреционками по-разному работает!
У меня XP.
Проверил под XP (брр), там тоже нормально работает.   ???
Ты точно мой проект используешь в том виде какой он был в архиве?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 10:18
О..., Оно еще и под разными опреционками по-разному работает!
У меня XP.
Проверил под XP (брр), там тоже нормально работает.   ???
Ты точно мой проект используешь в том виде какой он был в архиве?

Ты adjustSize() закомментировал?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:23
О..., Оно еще и под разными опреционками по-разному работает!
У меня XP.
Проверил под XP (брр), там тоже нормально работает.   ???
Ты точно мой проект используешь в том виде какой он был в архиве?

Абсолютно точно! Приаттачил твой вариант, можешь проверить что он.

===
Qt 4.6.0 - коммерческая версия
Qt Creator 1.3.0
Mingw
Windows XP


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 10:29
Наблюдение. Когда показывается вкладка минимальных размеров, то пользователь может менять размеры диалога как вздумается, если переключиться на первую вкладку, а потом снова на вторую, то размер диалога уже нельзя уменьшить до минимального, т.е. включаются ограничители.

При этом, если выбрать текущую вкладку 2 в дизайнере и сделать Preview, то ограничители срабатывают сразу же.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 14, 2009, 10:37
Абсолютно точно! Приаттачил твой вариант, можешь проверить что он.

===
Qt 4.6.0 - коммерческая версия
Qt Creator 1.3.0
Mingw
Windows XP
Проверил:
Linux Fedora11 - qt-4.5.3-9.fc11.x86_64
Windows XP - SDK Qt-4.6

Все работает.  ???


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:47
Проверил:
Linux Fedora11 - qt-4.5.3-9.fc11.x86_64
Windows XP - SDK Qt-4.6

Все работает.  ???

Что к чему???

Такой финт ушами тоже не помогает

Код
C++ (Qt)
  ui.tabWidget->setCurrentIndex(0);
  adjustSize();
  setMaximumSize(geometry().size());
  ui.tabWidget->setCurrentIndex(1);

И остальные подобные варианты с:
ui.tabWidget->setMinimumSize(ui.tabWidget->minimumSizeHint());


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 10:54
BRE, такого поведения нет?

(http://pic.ipicture.ru/uploads/091214/4Q15sWV4zW.gif)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:56
Проверил:
Linux Fedora11 - qt-4.5.3-9.fc11.x86_64
Windows XP - SDK Qt-4.6

Все работает.  ???

выкладываю 2 exe собранные Windows XP - SDK Qt-4.6.
Мой вариант - "dialogtest-my.exe"
Твой вариант - "dialogtest-yours.exe"

Поверь как они работают у тебя.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: spectre71 от Декабря 14, 2009, 10:58
BRE, такого поведения нет?
(http://pic.ipicture.ru/uploads/091214/4Q15sWV4zW.gif)

На твоем проекте - нет. Ресайз же заблокирован:
setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: lit-uriy от Декабря 14, 2009, 11:09
я думаю, что ещё и стили могут свою лепту вносить в поведение.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 12:43
На твоем проекте - нет. Ресайз же заблокирован:
setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);

Я закомментировал эту строчку. Она мешает пониманию проблемы :)

Вместо этого флага можно использовать более переносимое решение
Код
C++ (Qt)
setFixedSize(ui.tableWidget->minimumSizeHint());
 

Однако minimumSizeHint() возвращает размер только текущей вкладки, а не наибольший минимальный размер, как об этом заявлено в Qt Quarterly.

BRE, скачал твои исходники, вообще не понял странного поведения. В дизайнере если в "Preview" форму сжимать по горизонтали, то размеры упираются в минимальный размер. А вот в скомпилированном приложении можно форму уменьшать до такой степени, что виджеты начинают пересекаться. Этого не происходит в исходниках spectre, скорее всего у него где-то стоят дополнительные компановщики. Непонятно почему дизайнер в Preview ведет себя одинаково на обоих вариантах и по разному в компилируемом коде.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: BRE от Декабря 14, 2009, 14:28
Я уже сам ничего не понимаю.  :)
Сегодня проблемы со временем, как появиться буду дальше смотреть.
Нормально QTabWidget::minimumSizeHint считается только после визуализации....
Одни вопросы, нужно разбираться.  :)


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: lit-uriy от Декабря 14, 2009, 14:43
может можно тему к потолку прилепить?


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 14, 2009, 14:52
Насчет пересечения виджетов в исходниках BRE разобрался, тут устанавливаются заведомо неверные минимальные размеры:

Код
C++ (Qt)
ui.tabWidget->setMinimumSize(ui.tabWidget->minimumSizeHint());
 

Которые равны минимальному размеру второй вкладки, а не сумме минимальных размеров всех вкладок. Это при том, что по умолчанию выбрана вкладка с заведомо большим контентом. Т.е. minimumSizeHint() возвращает то, чего от него ожидают увидеть пользователи судя по названию. Т.е. пробегается по всем размерам существующих вкладок и возвращает минимальную из них. Нужен какой-то метод альтернативный типа maximumSizeHint(), но только, чтобы размеры возвращались не бесконечно возможные.

В общем я думаю задача свелась к тому, чтобы узнать размер страницы в скрытом QStackedLayout'e, если она еще не была ни разу показана.


Название: Re: Получаю не правильный размер widget'a и маленький вопрос о include
Отправлено: SABROG от Декабря 15, 2009, 21:10
Отдельно создал проект с использование QStackedLayout+QComboBox (для переключения страниц) вместо QTableWidget. Проверил - размер основного окна выставляется по максимальным размерам других страниц, не смотря на то, что в окне всего один QPushButton. Подумал, что проблема кроется все-таки в QTabWidget. Поместил его вместо QStackedLayout - поведение точно такое же: размер окна принял размер максимального размера скрытых вкладок. Т.е. то самое поведение, которого хочет spectre. Может я чего забыл или упустил, проект приаттачил.

P.S.: вызов adjustSize() не делал, т.к. это приводит к тому, что окно становится еще больше, вместо того, чтобы стать меньше.