Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: aljeshishe от Январь 13, 2010, 18:41



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


Название: Re: Отложенная иницализация окна
Отправлено: developer от Январь 13, 2010, 19:18
Можеш использовать паттерн State


Название: Re: Отложенная иницализация окна
Отправлено: Павел_F. от Январь 13, 2010, 21:50
Но проблема в том, что виртуальные функции нельзя использовать в конструкторах.
Это почему?
Вот код:
Код
C++ (Qt)
#include <QtGui>
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
public:
   MainWindow(QWidget *parent = 0) : QMainWindow( parent)
   {
myTest();
   }
   virtual void myTest()
   {
qWarning("void MainWindow::myTest()");
   }
};
 
 
class MainWindow2 : public MainWindow
{
   Q_OBJECT
public:
   MainWindow2( QWidget *parent = 0) : MainWindow( parent)
   {
myTest();
   }
   void myTest()
   {
qWarning("void MainWindow2::myTest()");
   }
};
 
Компилится, работает, виртуальная функция в конструкторе. Или имеется ввиду чисто виртуальные?


Название: Re: Отложенная иницализация окна
Отправлено: break от Январь 13, 2010, 21:59
Павел_

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

Код
C++ (Qt)
class MainWindow : public QMainWindow
{
   Q_OBJECT
public:
   MainWindow(QWidget *parent = 0) : QMainWindow( parent)
   {
myTest();
   }
   virtual void myTest()
   {
qWarning("void MainWindow::myTest()");
   }
};
 
class MainWindow2 : public MainWindow
{
   Q_OBJECT
public:
   void myTest()
   {
qWarning("void MainWindow2::myTest()");
   }
};
 

по вашей логике - раз они работаю то при создание экземпляра MainWindow2 должно вывестись "void MainWindow2::myTest()", но выведется
"void MainWindow::myTest()" т.к. виртуальные ф-ции можно использовать в к-рах, но они не будут работать как виртуальные - это действительно ограничение C++;

aljeshishe
думаю есть решения вашей проблемы
1) использовать отдельные ui для разных окон - в которых все Action руками расставлены по элементам меню как надо (можно использовать UILoader а можно и старым принципом)
2) сделать ф-цию init для базового окна и в ней а не в конструкторе вызывать setupUi -а уже в наследниках вызывать этот init тогда когда удобнее для создания элементов меню


Название: Re: Отложенная иницализация окна
Отправлено: Dendy от Январь 13, 2010, 22:00
Толку от такой виртуальной функции, которая вызывается из наследуемого класса.

По теме. В конструкторах можно и нужно создавать дочерние виджеты и делать setupUi(). Другое дело, что инициализировать их значениями нужно отдельно, здесь никакого стандартного способа в Qt нет. Нужно создавать свой виртуальный метод инициализации, который будет вызываться сразу же после конструктора. К примеру в Objective-C эта проблема решена тем, что у классов нет конструкторов вообще, только виртуальный метод init, обычно вызываемый после аллокации.


Название: Re: Отложенная иницализация окна
Отправлено: Павел_F. от Январь 13, 2010, 23:24
А для конкретно этой задачи не проще ли в классе завести список QList< QAction*> с действиями для меню. Рулить списком как пожелается где угодно, потом, например в showEvent, делать void QMenu::addActions ( QList<QAction *> actions )


Название: Re: Отложенная иницализация окна
Отправлено: Dendy от Январь 13, 2010, 23:35
Да, это вариант. Более того, возможно подойдёт стандартный QWidget::actions().