Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Отложенная инициализация окна

Автор: aljeshishe 12.1.2010, 23:56

Не знаю, возможно это все бред, но... в упрощенном виде проблема следующая
Есть базовый класс окна
class CMsgWindow : public QMainWindow
Тут определяются элементы интерфейса общие для дочерних классов окон
Например пункт меню Собщение\сохранить
Есть дочерние классы
class CInMsgWindow : public CMsgWindow
class COutMsgWindow : public CMsgWindow
В них определяется специфика.
Например пункты меню Собщение\принять и
Собщение\отправить соответственно.
Проблема в том, что не всегда вызывая в конструкторе setupUi(this), можно добиться нужного эффекта.
Например сначала в конструкторе CMsgWindow добавляется пункт "сохранить", а затем
в конструкторе CInMsgWindow добавляется "принять". В результате получается не тот порядок пунктов меню который нужен, обусловленный порядком вызова конструкторов. Можно привести более сложные примеры...
Все решила бы виртуализация функции инициализации элементов интерфейса. Тогда в дочернем классе можно вызывать функцию базового класса когда угодно, можно и вообще не вызывать.
Но проблема в том, что виртуальные функции нельзя использовать в конструкторах.
Отсюда вопрос, когда можно инициализировать элементы интерфейса, кроме как в конструкторе, при этом не меняя код создателя окна, оставляя его максимально простым:
CMsgWindow *p = new CInMsgWindow;
p->show();
Event'ы ?

Автор: Litkevich Yuriy 13.1.2010, 8:10

Цитата(aljeshishe @ 13.1.2010, 2:56) *
Но проблема в том, что виртуальные функции нельзя использовать в конструкторах.
разве?

Автор: ViGOur 13.1.2010, 10:02

Цитата(Litkevich Yuriy @ 13.1.2010, 8:10) *
разве?
угу, а ты сам подумай, объект еще не создан, а уже нужно обращаться к его виртуальной таблице, результат не однозначен короче. :)

Можно попробовать переопределить в классе CMsgWindow слот show и в нем уже вызывать нужную тебе функцию, ну и не забыть вызвать слот show базового класса.

Автор: aljeshishe 13.1.2010, 17:57

Как это переопределить слот show. А что это даст, он же не виртуальный? Этот слот вызывается при выполнении QApplication::processEvents(), который о нашем классе ничего не знает и вызовет оригинальную версию слота.
Вариантов то как решить дофига, можно и просто виртуальную функцию init сделать и вызывать ее при создании окна. Можно сделать startTimer(0) и поместить init в timerEvent(). Вопрос в том как сделать это правильно, красиво и элегантно. Я не знаю, может проблема вообще надуманная, и все решается гораздо проще, поэтому просьба отписаться тех кто сталкивался и красиво решил.

Автор: Litkevich Yuriy 13.1.2010, 18:19

Цитата(aljeshishe @ 13.1.2010, 20:57) *
который о нашем классе ничего не знает и вызовет оригинальную версию слота.
нет, он вызовет слот конкретного объекта. (с помощью сигнально-слотового соединения). А вообще можно обработать событие отображения. Вот ViGOur мне как-то давал код, я только посылку сигнала в нём сделал.
bool MainWindow::event(QEvent *p_event)
{
    if( p_event->type() == QEvent::ShowToParent)
        emit SigShow();

    return QWidget::event(p_event);
}

Автор: aljeshishe 13.1.2010, 18:40

Ну как вариант, только это событие будет вызываться по-моему при каждом показывании окна (сворачивание-разворачивение), а иницализироваться надо однажды. Добавить флажок и будет работать

Автор: kuler 13.1.2010, 19:18

а разве обязательно setupUI в конструкторе?

Автор: Litkevich Yuriy 13.1.2010, 23:12

Цитата(aljeshishe @ 13.1.2010, 21:40) *
Добавить флажок и будет работать
просто после того как отпала необходимость в инициализации, разорви соединение с сигналом SigShow

Автор: aljeshishe 14.1.2010, 18:31

Всем спасибо. Отложенный метод без труда вызывается через invokeMethod, так меньше кода.
А менюшки, тулбары видимо придется делать на основе контейнера c QAction'ами

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)