В JUCE большинство вещей, связанных с пользовательским интерфейсом, реализованы как подкласс компонента.
Некоторые из подклассов имеют концепцию компонента содержимого: все подклассы ResizableWindow
, который добавляет setContentOwned()
и setContentNonOwned()
методы, унаследованные всеми подклассами ResizableWindow
(особенно DocumentWindow
).
Чтобы определить содержание DocumentWindow
, пример кода в вашем вопросе использует setContentOwned()
в MainWindow
конструктор, который он получает из initialise()
в TestApplication
.
Для реализации навигации вы можете сделать следующее (есть другие способы сделать это):
1. Реализуйте навигацию в MainWindow
, чтобы у вас была навигационная логика c в одном центральном месте
2. Дайте каждой из ваших «Страниц» (давайте на один шаг назовем Страницу) указатель на MainWindow
. Для CreateAccount
это будет
Файл CreateAccount.h:
void setMainWindow(MainWindow * _mainWindow)
{
mainWindow = _mainWindow;
}
3. Также добавьте переменную экземпляра где-нибудь в класс CreateAccount
:
MainWindow * mainWindow;
и обновите конструктор:
CreateAccount()
: mainWindow(nullptr)
{
// ...
}
4. Измените код создания
и замените
mainWindow.reset (new MainWindow ("Test", new CreateAccount(), *this));
на:
CreateAccount * ca = new CreateAccount();
MainWindow * mw = new MainWindow ("Test", ca, *this)
ca->setMainWindow(mw);
mainWindow.reset(mw);
5. Реализуйте навигацию с помощью набора пользовательских методов (необходимо опубликовать c) в MainWindow
, например,
public:
void createProfileClicked()
{
// ...get entered data...
// ...process entered data...
// ...implement next navigation step...
// (you would create or recycle the "Page" for the next step here)
setContentOwned(
// ...
);
}
6. Вызовите этот метод из обработчика событий buttonClicked()
в CreateAccount
:
mainWindow->createProfileClicked();
Это только один способ реализовать то, что вы хотите. Все зависит от сложности вашего проекта.
Редактировать:
Мое предложение, данное в этом ответе, вводит циклические c зависимости классов.
Позвольте мне сначала переформулируйте то, что, по моему мнению, у вас сейчас есть, исходя из ваших комментариев:
mainwindow.h
#include "splashpage.h"
class MainWindow : public DocumentWindow
{
public:
// ...
void alaramReadyBtnClicked()
{
setContentOwned(new SplashPage(), false);
}
// ...
};
splashpage.h:
#include "mainwindow.h"
class SplashPage : public Component, public Button::Listener
{
public:
SplashPage()
: mainWindow(nullptr)
{}
void setMainWindow(MainWindow * _mainWindow)
{ mainWindow = _mainWindow; }
void buttonClicked (Button *) override
{
if (button == &tvbtnSomething) {
mainWindow->splashSomethingClicked();
}
}
private:
MainWindow * mainWindow;
};
Есть цикл c зависимость объявлений между MainWindow
и классами Page. Когда компилятор видит
mainWindow->splashSomethingClicked();
, он должен увидеть объявление MainWindow
, но в mainwindow.h
ему нужно объявление SplashPage
для этого:
void alaramReadyBtnClicked()
{
setContentOwned(new SplashPage(), false);
}
Сначала Хорошая практика заключается в использовании в ваших заголовочных файлах элементов защиты
например, mainwindow.h
// you need these include guards to prevent that the compiler
// sees this file a second time; it's a very good rule of thumb to always do this
// in you header files
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "splashpage.h"
class MainWindow : public DocumentWindow
{
// ...
};
#endif // !defined(MAINWINDOW_H)
В C ++ есть определенные c ситуации, для которых компилятору не требуется знать полное объявление: если вы используете только указатели или ссылки и не ссылаетесь на них. Затем вы можете использовать предварительное объявление имен классов.
Но вы не можете делать это только со всеми файлами заголовков. Потому что существует понятие «модуля компиляции».
Чтобы разорвать зависимость cycli c, измените свою ... Page.h:
#ifndef SPLASHPAGE_H
#define SPLASHPAGE_H
// don't include mainwindow.h here
class MainWindow; // forward declaration
class SplashPage : public Component, public Button::Listener
{
public:
SplashPage()
: mainWindow(nullptr)
{}
void setMainWindow(MainWindow * _mainWindow)
{
mainWindow = _mainWindow; // pointer copy does not need full declaration
}
// note: implementation not in this header file anymore
void buttonClicked (Button *) override;
private:
// ...
MainWindow * mainWindow; // does not need full declaration
};
#endif // !defined(SPLASHPAGE_H)
splashpage. cpp:
#include "mainwindow.h"
#include "splashpage.h"
void SplashPage::buttonClicked (Button *) override
{
if (button == &tvbtnSomething) {
mainWindow->splashSomethingClicked();
}
}
Если вы используете инструмент JUCE Projucer, вы можете легко добавить пары этих файлов, которые уже должны содержать элементы include guard.