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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Формы UI и минимизация кода  (Прочитано 4622 раз)
Alp
Гость
« : Сентябрь 16, 2009, 17:06 »

Надо сделать для диалога настроек 15 разных форм (точнее виджетов, которые будут уложены на нужное место кодом). Код (.h + .cpp) абсолютно идентичен (как я буду обрабатывать данные в формах, всякие там сигналы и проч. - другой вопрос, к делу не относится). Различаются они только именем включаемого файла ("ui_general.h", "ui_type1.h", ...), в которых совершенно одинаков задано имя класса:
Код
C++ (Qt)
namespace Ui {
   class Form: public Ui_Form {};
} // namespace Ui

Теперь вопрос: как бы мне не плодя лишние файлы (по паре на каждый виджет) обойти эту проблему?
Уже попробовал:
- сделать класс темплейтом. Думаю не надо говорить, что не вышло
- определять класс через #define. Тухло
- разносить деларацию класса c именем хедера и включать её после включения соответствующего ui_*.h-файла. Не выходит потому, что moc_*.cpp тоже хочет это хэдер, а там - неполное объявление формы

Код
C++ (Qt)
#include "ui_general.h"    //Here. Just this header differ.
 
class PrefWidget : public QWidget
{
   Q_OBJECT
   Ui::Form *ui;
public:
   PrefWidget(QWidget *parent = 0)
           : QWidget(parent), ui(new Ui::Form)    { ui->setupUi(this); }
   ~PrefWidget()    { delete ui; }
};
 
« Последнее редактирование: Сентябрь 17, 2009, 19:17 от alp » Записан
whirlwind
Гость
« Ответ #1 : Сентябрь 17, 2009, 16:33 »

может, можно динамически загружать ui-файлы с помощью QUiLoader?

чтото вроде

Код:

QWidget* ui;

PrefWidget::PrefWidget( QWidget *parent , QString uiName)
{
     QUiLoader loader;
     QFile file( uiName );
     file.open(QFile::ReadOnly);
     ui = loader.load(&file, this);
     file.close();
}

правда, непонятно, как setupUi вызвать.
Записан
Alp
Гость
« Ответ #2 : Сентябрь 17, 2009, 17:02 »

Интересная мысль. Я про такую штуку вообще не знал.
А setupUi(QWidget*) тут уже будет не нужен, т.к. методо load() вернет указатель на готовый виджет. В ui_*.h метод обновляющий UI нужен потому, что класс там (если глянуть в автосоздаваемый исходник) не наследует QWidget.
Записан
Alp
Гость
« Ответ #3 : Сентябрь 17, 2009, 17:22 »

Одна непонятка - что делать с сигналами, если надо свой добавить? Связать сигнал от кнопки, например, со своим собственным с помощью дизайнера мне не удалось.
Записан
Alp
Гость
« Ответ #4 : Сентябрь 17, 2009, 19:16 »

В общем, в рамках требуемого мне - разобрался.
Надо было сделать кучку форм, которые будут укладываться на нужное место в списке опций. От этих формочек требовалось сообщать лишь одно: "на мне изменили что-то", т.е. для каждой хватило сигнала modified(QWidget*). Реализовано через QUiLoader (не забываем подключать uitools  в проекте ;-)), за что спасибо огромное товарищу whirlwind.
В итоге получилась обертка над QUiLoader'ом, умеющая загружать формы, искать нужные контролы (через RTTI) и реэмитить сообщения от них.

Код
C++ (Qt)
#ifndef QCUSTOMUILOADER_H
#define QCUSTOMUILOADER_H
 
#include <QWidget>
#include <QString>
 
class QUiLoader;
class QFile;
 
class QCustomUiLoader : public QWidget
{
   Q_OBJECT
 
   QUiLoader *loader;
 
   QWidget *lastLoaded;
 
public:
   QCustomUiLoader(QWidget* parent = 0);
   ~QCustomUiLoader();
 
   QWidget* Load(const QString& filename, QWidget* parent = 0);
   QWidget* LastLoaded() const      { return lastLoaded; }
 
signals:
   void modified(QObject*);
 
public slots:
   void IndexChanged(int i)        { emit modified( sender()->parent() ); }
   void StringChanged(QString)     { emit modified( sender()->parent() ); }
   void EmptyChanged()             { emit modified( sender()->parent() ); }
};
 
#endif // QCUSTOMUILOADER_H
 

Код
C++ (Qt)
#include "QCustomUiLoader.h"
 
#include <QFile>
#include <QUiLoader>
 
#include <QLineEdit>
#include <QComboBox>
#include <QAbstractButton>
 
QCustomUiLoader::QCustomUiLoader(QWidget* parent) :
   QWidget(parent),
   loader(new QUiLoader(this)),
   lastLoaded(0)
{
 
}
 
QCustomUiLoader::~QCustomUiLoader()
{
}
 
QWidget* QCustomUiLoader::Load(const QString& filename, QWidget* parent)
{
   //
   // Load UI
   //
 
   lastLoaded = 0;
 
   QFile file(filename, this);
   file.open(QFile::ReadOnly);
 
   if( !file.isOpen() )
       return lastLoaded;
 
   lastLoaded = loader->load(&file, parent);
 
   file.close();
 
   //
   // Connect UI signals
   //
 
   foreach(QObject* o, lastLoaded->children())
   {
       QLineEdit *le = 0;
       QComboBox *cb = 0;
       QAbstractButton* ab = 0;
 
       if( le = qobject_cast<QLineEdit*>(o) )
       {
           connect(le,
                   SIGNAL(textChanged(QString)),
                   SLOT(StringChanged(QString)));
       }
       else if( cb = qobject_cast<QComboBox*>(o) )
       {
           connect(cb,
                   SIGNAL(currentIndexChanged(int)),
                   SLOT(IndexChanged(int)));
 
           connect(cb,
                   SIGNAL(editTextChanged(QString)),
                   SLOT(StringChanged(QString)));
       }
       else if( ab = qobject_cast<QAbstractButton*>(o) )
       {
           connect(ab,
                   SIGNAL(clicked()),
                   SLOT(EmptyChanged()));
       }
   }
 
   //
   // Return result
   //
 
   return lastLoaded;
}
 
Записан
SLiDER
Гость
« Ответ #5 : Сентябрь 19, 2009, 00:05 »

В общем, в рамках требуемого мне - разобрался.
...
В итоге получилась обертка над QUiLoader'ом, умеющая загружать формы, искать нужные контролы (через RTTI) и реэмитить сообщения от них.

Я Вас поздравляю с заслуженной победой Улыбающийся , однако замечу, что qobjec_cast не имеет ни какого отношения к RTTI, а использует в своей работе Qt-шную метаинформацию, и именно по этому умеет работать только с типами явно или не явно наследованными от QObject-та.
Записан
Alp
Гость
« Ответ #6 : Сентябрь 19, 2009, 00:07 »

В общем, в рамках требуемого мне - разобрался.
...
В итоге получилась обертка над QUiLoader'ом, умеющая загружать формы, искать нужные контролы (через RTTI) и реэмитить сообщения от них.

Я Вас поздравляю с заслуженной победой Улыбающийся , однако замечу, что qobjec_cast не имеет ни какого отношения к RTTI, а использует в своей работе Qt-шную метаинформацию, и именно по этому умеет работать только с типами явно или не явно наследованными от QObject-та.

Тьфу, начал читать, уж додумывая на ходу: "поздравляю вас... с изобретением давно известного велосипеда" =))
Ладно, значит не RTTI, решил что QTшный работает так же как классический dynamic_cast.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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