Russian Qt Forum
Августа 26, 2025, 20:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Еще одно окно типа *.ui  (Прочитано 8382 раз)
pupapum
Гость
« : Февраля 08, 2008, 12:48 »

Привет ребят. У меня есть окно типа QMainWindow, создананное как .ui и оно у меня главное. Я создал еще одно окно типа ui, но не могу разобраться как его запустить при запущенном первом. Можете привести исходники файлов .h и .cpp, как должен выглядеть класс этой формы. Извините, если мысли варажаю не очень понятно. =). Вторая форма наследуется от QMainWindow и имя у нее CodeInput.ui. Спасибо.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #1 : Февраля 08, 2008, 13:48 »

у тебя второй класс называется CodeInput?
тогда где-нибудь в коде первой формы, пиши
CodeUnput *form2 = new CodeUnput(this);  // для создания
form2->show(); // для отображения
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Karl-Philipp
Гость
« Ответ #2 : Февраля 08, 2008, 13:50 »

может я ошибаюсь, но сам делал так.

Во-первых, создавал класс, который наследует ui-класс и нужный класс (у меня - QDialog). Примерно это выглядит так:

class PMD : public QDialog, private Ui::Dialog
{
...
};

Во-вторых, создал указатель на PMD класс и показывал его с помощью show() или прятал, соответсвенно - hide();
« Последнее редактирование: Февраля 08, 2008, 20:51 от terlan » Записан
vregess
Гость
« Ответ #3 : Февраля 09, 2008, 07:35 »

может я ошибаюсь, но сам делал так.

Во-первых, создавал класс, который наследует ui-класс и нужный класс (у меня - QDialog). Примерно это выглядит так:

class PMD : public QDialog, private Ui::Dialog
{
...
};

Во-вторых, создал указатель на PMD класс и показывал его с помощью show() или прятал, соответсвенно - hide();
Возможно ты не ошибаешься. Вот более подробно:
Код:
// объявление и реализация класса
#include "ui_CodeInput.h"

class CodeInput: public QMainWindow, private Ui::CodeInput
{
  CodeInput(QWidget *parent=0, Qt::WindowFlags flags=0);
...
};
...
CodeInput::CodeInput(QWidget *parent, Qt::WindowFlags flags)
  :QMainWindow(parent, flags)
{
  setupUi(this);
}
..

// конец

// где-нибудь в первом "главном" окне
CodeInput *window=new CodeInput(this); // или без this
window->show();
Записан
pupapum
Гость
« Ответ #4 : Февраля 09, 2008, 13:35 »

спасибо, пробую...
Записан
Dodge
Гость
« Ответ #5 : Февраля 11, 2008, 17:09 »

+ можно воспользоватся QUiLoader'ом:

Код:
QUiLoader uiloader;
QFile uiFile( "myform.ui" );
uiFile.open( QIODevice::ReadOnly );
QWidget * myWindow = uiloader.load( &uiFile );
uiFile.close();

QPushButton * button = myWindow->findChild( "MyPushButton" );
...


 Смеющийся
Записан
Karl-Philipp
Гость
« Ответ #6 : Февраля 12, 2008, 11:24 »

+ можно воспользоватся QUiLoader'ом:

Код:
QUiLoader uiloader;
QFile uiFile( "myform.ui" );
uiFile.open( QIODevice::ReadOnly );
QWidget * myWindow = uiloader.load( &uiFile );
uiFile.close();

QPushButton * button = myWindow->findChild( "MyPushButton" );
...


 Смеющийся


Dodge,

можно и QUiLoader'ом. А если, например, нужно дописать какие-то методы к загружаемому интерфейсу (а методы точно придется дописывать, ведь созданная форма ui (в посте pupapum) наследует QMainWindow)? В предложеном Вами варианте нельзя же так сделать?
Или я не прав?
Записан
Dodge
Гость
« Ответ #7 : Февраля 12, 2008, 17:05 »

неправ  Показает язык

вся соль тут:
Код:
...
QPushButton * button = myWindow->findChild<QPushButton*>( "MyPushButton" );//тут было немного неверно, поправил
...

мы можем получить указатель на любой виджет через его парента, зная его objectName. Парента мы знаем, указатель на него возвращает QUiLoader.

следовательно чтоб создать обработчик для кнопки "MyPushButton" делаем следуещее:
1. Делаем "класс функционала", в который обрабатывает все нужные события, в нашем случае - нажатие на кнобку
Код:
class MyClass : public QObject {
    Q_OBJECT
public:
    MyClass();
    ~MyClass();
...
public slots:
    void actionButton();
};

void MyClass::actionButton() {
    ... // обработчик нажатия кнопки
}


далее:
Код:

int main(...) {
    ... //загрузка ui-файла, указатель на парента myWindow (см. перд пост)
    QPushButton * button = myWindow->findChild<QPushButton*>( "MyPushButton" );
   
    MyClass myclass;

    connect( button, SIGNAL( clicked() ), myclass, SLOT( actionButton() ) );

}


Собственно все.
Такой способ проэктирования заставляет программиста, "оторват" функционал от gui, а это ИМХО есть - правильно.

З.Ы. Вообще, с появлением модуля Qt Script все стало еще проще, если интересно я могу выложить несколько примеров создания приложения с исп динамической загрузки gui, при помощи скрипта.
Записан
Karl-Philipp
Гость
« Ответ #8 : Февраля 12, 2008, 17:18 »

интересное решение Улыбающийся

Кроме того, очень хотелось бы посмотреть на примеры создания приложения с исп динамической загрузки gui, при помощи скрипта. Выложите, пожалуйста.
Записан
Dodge
Гость
« Ответ #9 : Февраля 13, 2008, 13:49 »

Как и обещал, привожу пример загрузки gui при помощи Qt Script.

Для начала нам нужно расширить базовые возможности  Qt Script, и добавить ряд глобальных объектов, для более гибкого проектирования.
Я написал небольшое расширение(ScriptEngine) для стандартного QScriptEngine, которое имеет рад особенностей:
1. Поддерживает систему плагинов.
Это очень важно, т.к. это позволяет нам расширять функционал движка "на ходу". Т.е. если нам чегото не хватает, то мы это пишем и подгружаем(хоть в динамике).
На данный момент мой движок поддерживает 2 типа плагинов:
- статические;
- контекстные;
Их различие в том, что статический плагин может содержать в себе только набор некоторых функций, а контекстный, может еще содержать в себе некоторые классы, которые он(плагин) может зарегистрировать в контексте движка, и соответственно эти классы станут доступны непосредственно из скрипта.
2. Мультиконтекстность. Это значит что каждый скрипт, может выполнятся в своем независимом контексте.

Ниже декларация движка:
Код:
class ScriptEngine : public QObject {
Q_OBJECT
Q_PROPERTY( bool autoDrop READ autoDrop WRITE setAutoDrop )
Q_PROPERTY( bool internalErrorOutput READ internalErrorOutput WRITE setInternalErrorOutput )
protected:
QScriptEngine * se;

bool engineautodrop, showerror;

static QList<QObject*> plugins;
static QHash<QString,ScriptEngine*> crengines;
static ScriptEngine * firstEngine;

public:
ScriptEngine( QObject * parent=0 );
~ScriptEngine();

bool autoDrop() { return engineautodrop; }
bool internalErrorOutput() { return showerror; }

Q_INVOKABLE static ScriptEngine * getFirstEngine( QObject * parent=0 );
Q_INVOKABLE static ScriptEngine * newEngine( QString name );
Q_INVOKABLE static ScriptEngine * engine( QString name );
Q_INVOKABLE static bool dropEngine( QString name );
Q_INVOKABLE static bool killEngine( QString name );
Q_INVOKABLE static void dropAll();
Q_INVOKABLE static void killAll();
Q_INVOKABLE static QStringList engineNames();

Q_INVOKABLE static bool addPlugin( QString filename );
Q_INVOKABLE static void loadAllPluginFromDir( QString path );
protected:
static bool addPlugin( QObject * plugin );

QStringList configure( bool v=false );

private:
void setObjectName( QString name ) { QObject::setObjectName( name ); }

public slots:
void setAutoDrop( bool e ) { engineautodrop = e; }
void setInternalErrorOutput( bool e ) { showerror = e; }
void dropEngine();

void executeEngine( QString str, QStringList args=QStringList(), bool v=false );

signals:
void error( int line, QString text, QString enginename );

};

Не буду углубляться в детали, скажу лиш то, что для постановки скрипта на выполнение требуется вызвать функцию executeEngine, которая принимает ряд аргументов:
str - если имя файла, то выполняется файл, если нет, то интерпретируется как скрипт;
args - аргументы, первый(если есть) - имя функции в скрипте, которую необходимо запустить, остальные параметры передаются как аргументы для данной функции;
v - для отладки, нам не интересен.


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

Интерфейс плагина:
Код:
class StaticModuleInterface {
public:
virtual ~StaticModuleInterface() {}

virtual QString moduleName() = 0;  // возвращает имя модуля, по которому можно будет обращатся к нему из скрипта

};
Q_DECLARE_INTERFACE( StaticModuleInterface, "RES.ScriptEngine.StaticModuleInterface/1.0" )

Выше я упоминал о 2 типах плагинов, но тут только 1, статический, контекстный нам пока и не нужен))

загрузчик ui - файлов:
Код:
class UiLoaderPlugin :
public QObject,
public StaticModuleInterface
{
Q_OBJECT
Q_INTERFACES(StaticModuleInterface)
Q_PROPERTY( QString workingDirectory READ workingDirectory )
Q_PROPERTY( QStringList pluginPaths READ pluginPaths )
Q_PROPERTY( QStringList availableWidgets READ availableWidgets )

private:
QUiLoader * uiloader;

public:
UiLoaderPlugin( QObject * parent=0 );
~UiLoaderPlugin();

QString moduleName(); // вернет uiloader, подробно смотри выше StaticModuleInterface

QStringList pluginPaths();
QString workingDirectory();
QStringList availableWidgets();

Q_INVOKABLE QWidget * load( QString filename, QWidget * parent=0 );
Q_INVOKABLE QAction * createAction( QObject * parent = 0, QString name = QString() );
Q_INVOKABLE QActionGroup * createActionGroup( QObject * parent = 0, QString name = QString() );
Q_INVOKABLE QLayout * createLayout( QString className, QObject * parent = 0, QString name = QString() );
Q_INVOKABLE QWidget * createWidget( QString className, QWidget * parent = 0, QString name = QString() );

public slots:
void addPluginPath( QString path );
void clearPluginPaths();
void setWorkingDirectory( QString path );

void appExec();
void appQuit();

};

В принципе если вы в ассистенте посмотрите класс QUiLoader, то особых отличий от вышеприведенного плагина не увидите, плагин выполняет роль транслятора функциональности класса QUiLoader, для движка.
+ 2 функции, которые будут полезны при работе с gui appExec - QApplication::exec() и appQuit - QApplication::quit().

Ну а далее все просто до безобразия:
1. Засовываем загрузщик ui - файлов в шаред либрари.
2. Пишем программку которая будет выполнять роль интерпретатора.
Код:
#include "ScriptEngine.h"

#include <QApplication>
#include <QStringList>

int main( int a, char ** b ) {
QApplication app( a, b );

QStringList args( app.arguments() );
args.takeAt( 0 );

if ( args.count() == 0 )
return 0;

ScriptEngine e;

e.loadAllPluginFromDir( app.applicationDirPath() );

if ( args.count() > 0 ) {
QString filename = args.takeAt( 0 );
e.executeEngine( filename, args, v );
}

return 0;
}
Тут еще стоит обратить внимание на функцию loadAllPluginFromDir. Она пытается загрузить все библиотеки из указанного каталога, если загружаемая библиотека - есть плагин, то загружает его, если нет то игнорирует.
3. Нарисовать форму в дизайнере, и написать скрипт который будет ее подгружать.


Собственно привожу уже заезженный пример загрузки окна с кнопкой(кнопка называется - myButton):

Код:

function myButtonClick() {
print( "Button pressed!" );
}

var win = uiloader.load( "myform.ui" );

if ( win == null ) {
print( "can't load ui-file" );
uiloader.appQuit();
}

var button = win.findChild( "myButton" );

if ( button == null ) {
print( "bad ui-file" );
uiloader.appQuit();
}

button.clicked.connect( myButtonClick() );

win.show();

uiloader.appExec();


Соответственно в функции myButtonClick может быть все что угодно. Также никто не мешает коннектить сигнал clicked кнопки к другим объектам, в том числе и плагинам/модулям движка.

Приклеел исходники того что я тут втирал))
Записан
ритт
Гость
« Ответ #10 : Февраля 13, 2008, 14:47 »

эх...жаль, одмин не прикрутил вику - хороший материал для фака/триков
Записан
Dodge
Гость
« Ответ #11 : Февраля 13, 2008, 15:42 »

эх...жаль, одмин не прикрутил вику - хороший материал для фака/триков

Впринципе согласен. На форуме есть некоторое количество материала которое хотелось бы видеть в виде структурированного мануала/пособия/фака.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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