LINUX.ORG.RU

Базовые визуальные классы в Qt

 , ,


0

3

Здравствуйте! Облазила кучу ссылок в гугле, но так и не нашла ничего полезного((

Что надо.

Есть форма MyBaseWindow, наследуемая от QMainWindow. На ней есть какие-то элементы.

Есть еще несколько форм MyForm1. MyForm2,... Все они имеют то же самое, что есть у BaseWindow и что-то свое.

Как наследовать формы в qt creator?

При создании формы нет возможности унаследовать ее от чего-то своего.

В дизайнере для формы нет опции «преобразовать в...» (promote to).

Создавала MyWindow1 как наследника от QWidget.

Потом меняла в h и cpp файлах QWidget на MyBaseWindow.

Если не считать, что в дизайнере все, что есть у предка не отображается, то вроде все работает. при запуске у MyForm1 есть и то, что на этой форме, и то, что на родительской MyBaseWindow.

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

Неужели никто и никогда не наследовал формы в Qt и я хочу странного?((

Вот тут похожий вопрос

Собственно в выводе вот это:

QLayout: Attempting to add QLayout «» to MyForm «MyBaseWindow», which already has a layout

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

Это ты создаешь layout для виджета, который уже имеет layout. Старый layout надо явно удалять перед установкаой нового.

grondek
()

Нельзя преобразовать наследника одного класса Qt в наследника другого класса. Если я правильно понял, то ты хочешь преобразовать QMainWindow в наследника QWidget.

У QMainWindow уже есть свой layout, который нельзя менять (то есть можно, но нет смысла). А для преобразования можно использовать QMainWindow::centralWidget.

grondek
()

Как наследовать формы в qt creator?

Никак, это вам не нужно.

Неужели никто и никогда не наследовал формы в Qt и я хочу странного?((

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

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

Нельзя преобразовать наследника одного класса Qt в наследника другого класса. Если я правильно понял, то ты хочешь преобразовать QMainWindow в наследника QWidget.

Почти.

MyBaseWindow наследуется от QMainWindow.

MyForm создаю как наследника от QWidget, потом QWidget вручную меняю на QMainWindow.

А как можно?

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

Никак, это вам не нужно.

Вы как-то неправильно понимаете принципы построения интерфейсов.

Есть 100 форм. На каждой из них, например, 5 одинаковых кнопок, которые должны быть одинаково расположены, быть одинакового размера и делать что-то одинаковое. Ну, например, кнопка «выход», кнопка «сохранить что-то».

Чем так плохо наследование? писать close() 100 раз или 100 раз кнопки выставлять на форму и писать коннект их с какими-то слотами, пусть и унаследованными.

попробую рассказать как лучше.

Расскажите, пожалуйста )

traktor
() автор топика

Создай отдельный класс виджета, накидай на него те кнопочки, что на каждой форме, на каждую форму кидай этот виджет, вот и всё.

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

Есть 100 форм. На каждой из них, например, 5 одинаковых кнопок, которые должны быть одинаково расположены, быть одинакового размера и делать что-то одинаковое. Ну, например, кнопка «выход», кнопка «сохранить что-то».

Вот пример из жизни так из жизни. Ну да ладно — один раз создаем форму с пятью кнопками, прописываем всю логику в классе формы. Потом динамически в цикле 100 раз создаем объекты получившегося класса и кидаем их в лейаут на главную форму.

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

Так не нужно. Можно MyForm создать как населедника от QMainWindow.

Но часто не имеет смысла наследовать QMainWindow. Наследуется QWidget и вставляется в MainWindow методом setCentralWidget или в дизайнере.

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

Наглая ложь.

Ясно, что технически можно сделать что угодно. Непонятно, что конкретно ТС хочет и зачем там наследование. Кучи экземпляров наследников QMainWindow явно пахнут плохим кодом.

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

Появилось два вопроса ))

1. Если мой виджет, например - четыре кнопки в углах формы.

А на MainWindow должны быть эти четыре кнопки в углах и еще что-то в центре.

Я так понимаю, можно такое сделать только если ui у MyWidget - указатель в public.

Тогда :

mw->ui->horizontalLayout->insertWidget(2, ui->radioButton);

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

2. Во-первых, свой виджет (что в случае с plugin, что в случае с promotion) - это картирка/набор разных виджетов.

Там может быть логика в любых количествах или это, мягко говоря, моветон?)

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

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

Ну вот все тот же пример...

Надо 100 разных форм.

Но у всех у них совершенно одинаковые 5 виджетов. Хоть кнопки, хоть еще что. И даже в одном и том же месте они на всех формах должны быть. И делают одно и то же.

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

1. Если мой виджет, например - четыре кнопки в углах формы.
А на MainWindow должны быть эти четыре кнопки в углах и еще что-то в центре.
Я так понимаю, можно такое сделать только если ui у MyWidget - указатель в public.

Тут у вас нарушение инкапсуляции, так нельзя, он не зря в привате по-умолчанию.

Предположим, что нам нужно получить такую штуку — четыре кнопки по углам и произвольный виджет по середине.
Что мы делаем, самый наглядный вариант:
1) Создаем класс формы с четырьмя кнопками. Добавляем четыре метода на установку лейблов на кнопки. Добавляем четыре сигнала для отлова нажатий на них. Добавляем метод, принимающий указатель на QWidget, и вставляющий его в центр например QGridLayout'a.

2) Создаем еще класс, в котором любая логика (Worker). Создаем там центральный объект (Central). Создаем объект формы из пункта 1 (Form). Закидываем Central на Form, подписываемся на сигналы обоих и радуемся жизни.

2. Во-первых, свой виджет (что в случае с plugin, что в случае с promotion) - это картирка/набор разных виджетов.
Там может быть логика в любых количествах или это, мягко говоря, моветон?)

Да, конечно, может быть.

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

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

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

Дизигнер - рак. Не советую вам продолжать им пользваться.

Обосновать можете? Вот то, что реализация сложных интерфейсов в коде на порядок осложняет поддержку — факт.

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

Виджеты добавляла в «дизигнере», так удобнее. Там из-за наследования лайауты не ужились, разве дело в дизайнере?

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

Вот то, что реализация сложных интерфейсов в коде на порядок осложняет поддержку — факт.

Чем сможете подтвердить? 3 года пилил сложные интерфейсы в коде - все было ок. По дороге выпилил остатки xml-рака из проекта.

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

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

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

Все таки я не понимаю, почему не наследование...

То, что его нет - на то есть причины (нарушение каких-то qt-принципов и тд) или просто пока и без него можно обойтись и ладно?

Вот надо мне по нажатию на одну из 5 кнопок моего виджета что-то сделать, а что именно зависит от какого-то поля в Worker`е.

В MyWidget есть:

int buf;
void slotClickedButton1()
{
if (buf!=100500)
...
else
...
}

В Worker (наследник MyWidget) просто писали бы где-то

buf = 100500;

А если MyWidget добавлен на форму Worker`а - что-то страшное получается:

ui->myWidgetOnWorkerForm->buf = 100500;
Или даже
ui->myWidgetOnWorkerForm->setBuf(100500);

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

2) Создаем еще класс, в котором любая логика (Worker). Создаем там центральный объект (Central). Создаем объект формы из пункта 1 (Form). Закидываем Central на Form, подписываемся на сигналы обоих и радуемся жизни.

Немного не так сделала - все слоты к кнопкам виджета в классе самого виджета)

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

Все таки я не понимаю, почему не наследование...

Не нужно наследование там, где можно обойтись включением. У Вас повторяющийся участок - это те 4 кнопки, которые кочуют из одного окна в другое. Вот из них, как Вам советовали выше, делаете отдельный класс, хотите из QWidget, хотите из QFrame, и используете (включаете) его в своих формах как поле класса. Оно и логичнее - эти 4 кнопки фрагмент формы, а не отдельная форма. Наследование было бы логично во втором случае.

Открою страшную тайну - объект своего класса можно даже в ui-формы включать, если .ui руками подправить. Правда, насколько я понимаю, это нерекомендуемый метод. Рекомендуемый - сделать из своих классов плагин к дизайнеру, но это уже сложнее. В большинстве случаев достаточно включать программно в cpp, не забывая про layout-ы. Собственно, во всех demos и examples к Qt так и делается, виджеты включаются в окна непостредственно из cpp. Там же можно посмотреть разные комбинации с layout-ами.

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

Чем сможете подтвердить?

3 года пилил сложные интерфейсы в дизайнере - все было ок. По дороге выпилил остатки интерфейса из кода.

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

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

Ничего править руками не нужно — достаточно использовать пункт меню «Преобразовать в ...».

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

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

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