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

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

Страниц: [1] 2 3 ... 6   Вниз
  Печать  
Автор Тема: Получаю не правильный размер widget'a и маленький вопрос о include  (Прочитано 38886 раз)
n4ela
Гость
« : Декабрь 13, 2009, 17:24 »

Есть главное окно, на нем центральный виджет на котором vertical layout и в нем мой виджет, в конструкторе моего widget'a вызывывается метод restart и в нем я должен получить ширину и высоту виджета, но данные получаются не правильные, хотя в методе paintEvent высота и ширина уже правильные.

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

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

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

Тролли вроде рекомендуют по первому способу, но дизайнер генерирует код по второму варианту. В чем разница?
« Последнее редактирование: Декабрь 13, 2009, 17:36 от n4ela » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Декабрь 13, 2009, 17:38 »

Подумай над такой темой:
находясь в конструкторе объекта, объект уже сконструирован? Т.е. его размеры уже обсчитаны и известны?
Записан

Юра.
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #2 : Декабрь 13, 2009, 17:39 »

>>И еще маленький вопрос о инклудах.
смешиваешь разные темы в одну, да и вопрос такой уже был (см. forward declaration)
Записан

Юра.
spectre71
Гость
« Ответ #3 : Декабрь 13, 2009, 18:02 »

Подумай над такой темой:
находясь в конструкторе объекта, объект уже сконструирован? Т.е. его размеры уже обсчитаны и известны?

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

Сообщений: 3880


Просмотр профиля WWW
« Ответ #4 : Декабрь 13, 2009, 18:38 »

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

>>И вообще, с конструктором не связано,
Как это не связано, пока конструктор не завершился, объект не сконструирован.
Нет ни одного размера, т.к. компоновщик ещё не вызывал методы (ещё не существующего виджета) для получения/управления размерами
« Последнее редактирование: Декабрь 13, 2009, 18:41 от lit-uriy » Записан

Юра.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Декабрь 13, 2009, 19:10 »

>>Да - сконсруирован уже в начале конструктора.
В начале конструктора сконструирован только базовый класс, то что память выделилась, ещё ни о чём не говорить, там кроме мусора ещё ничего нет
Не только члены и базовые классы - сам экземпляр инициализирован, указатель на VMT прописан, виртуальные методы в конструкторе вызывать можно.

Размеров в конструкторе не получить - это правильно поскольку размеры зависят от (многих) парентов и лайаутов. Но плохо что их вообще нельзя получить до show и часто приходится заниматься неприятными вычислениями длин/ширин или полагаться на мудрость лайаутов.
Записан
SABROG
Гость
« Ответ #6 : Декабрь 13, 2009, 19:28 »

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

Не только члены и базовые классы - сам экземпляр инициализирован, указатель на VMT прописан, виртуальные методы в конструкторе вызывать можно.
+10
Маленькое уточнение. Виртуальные методы в конструкторе вызывать можно, но не как виртуальные, поскольку в C++ конструкторы не виртуальны, на мой взгляд один из самых больших недостатков C++, - постоянно приходится делать init методы. Грустный

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

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

Записан
spectre71
Гость
« Ответ #8 : Декабрь 13, 2009, 19:50 »

Насколько я помню если выбросить исключение в конструкторе, то объект создан не будет, однако нет гарантии того, что выделенная память будет освобождена, это зависит от компилятора не смотря на то, что комитет ISO/ANSI по С++ считает, что память должна освобождаться неявно.

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

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

А как насчет adjustSize вызываемого в конструкторе? И получения размеров после него, как правило корректных.
Так что считаю что проблема надумана троллями.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Декабрь 13, 2009, 20:26 »

Маленькое уточнение. Виртуальные методы в конструкторе вызывать можно, но не как виртуальные, поскольку в C++ конструкторы не виртуальны, на мой взгляд один из самых больших недостатков C++, - постоянно приходится делать init методы. Грустный
Улыбающийся Конструктор не может быть виртуальным поскольку именно его вызов прописывает VMT. А также лучше сказать: при конструировании базового класса будут вызываться его виртуальные методы (а не виртуальные методы порожденного класса).

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

Edit:
А как насчет adjustSize вызываемого в конструкторе? И получения размеров после него, как правило корректных.
А как "не правило"? Улыбающийся Я пробовал и иногда adjustSize работает, иногда нет. Как я понял зависит от флагов (Fixed, Expanded) - тоже не дело
« Последнее редактирование: Декабрь 13, 2009, 20:36 от Igors » Записан
SABROG
Гость
« Ответ #10 : Декабрь 13, 2009, 20:43 »

А как насчет adjustSize вызываемого в конструкторе?

Если это работает, то это еще один способ обхода проблемы. А проблема не надумана троллями, просто она есть и люди всё продолжают и продолжают создавать подобные темы. В документации я не нашел об этом упоминания.
Записан
BRE
Гость
« Ответ #11 : Декабрь 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'е? Кто сможет это посчитать?
Записан
spectre71
Гость
« Ответ #12 : Декабрь 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" )
Записан
SABROG
Гость
« Ответ #13 : Декабрь 13, 2009, 20:50 »

Кто сможет это посчитать?

Как я и писал в конце метода вызывать qApp->processEvents() и получать после него или ставить в очередь вызов слота (Qt::QueuedConnection). Естественно, что размеры виджета могут тут же поменяться на другие после того как они уже были получены, просто нужно дополнять документацию, чтобы народ не удивлялся.
Записан
spectre71
Гость
« Ответ #14 : Декабрь 13, 2009, 20:57 »

Камрады, что то я не соображу с размерами...
Вот типичный код:
Код
C++ (Qt)
...
Какой размер должен быть известен в конструкторе объекта edit, когда при его конструировании еще не известно в какой layout он будет помещен (и будет ли вообще), сколько еще виджетов будет в этом layout'е? Кто сможет это посчитать?

По-умолчанию для текущего фонта, текущего текста, текущих ограничений на размер, итд...
Записан
Страниц: [1] 2 3 ... 6   Вверх
  Печать  
 
Перейти в:  


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