Hallo alle zusammen. Ich bin ein Android-Entwickler mit wenig Erfahrung. Und heute möchte ich die Erfahrungen mit der Entwicklung eines Bildungsprojekts in C ++ und Qt mit einer einfachen Navigation zwischen den Bildschirmen teilen . Ich würde mich über Kritik oder Ergänzungen zu meiner Lösung freuen und hoffe, dass sie jemandem helfen und das Leben leichter machen kann.
Aufgabe
Bevor wir beginnen, definieren wir zwei Begriffe, damit am Ende keine Verwirrung entsteht.
Fenster ist das häufigste Fenster in Fenstern oder anderen Betriebssystemen.
Bildschirm - eine Art von Inhalt, der innerhalb des Fensters durch andere ersetzt werden kann.
, - Trello, , . ? , .
, , QStackedWidget . - .
. , , . .
, , , :
.
.
.
.
— BaseFragment. , . , .
class BaseFragment: public QFrame {
Q_OBJECT
signals:
//
public:
BaseFragment();
~BaseFragment();
// -
};
BaseFragment. , QStackedWidget .
class LoginFragment: public BaseFragment
class StartFragment: public BaseFragment
class RegistrationFragment : public BaseFragment
, , , . , , .
class BaseScreensFactory {
public:
BaseScreensFactory();
~BaseScreensFactory();
virtual BaseFragment* create(QString tag);
virtual QString createStart();
};
:
create(QString tag) — ( );
createStart() — .
:
// screensfacrory.h
namespace screens {
static const QString SPLASH_TAG = "splash";
static const QString START_TAG = "start";
static const QString LOGIN_TAG = "login";
static const QString REGISTRATION_TAG = "registration";
// .....
};
class ScreensFactory: public BaseScreensFactory {
public:
ScreensFactory();
~ScreensFactory();
BaseFragment* create(QString tag) override;
QString createStart() override;
};
// screensfacrory.cpp
BaseFragment* ScreensFactory::create(QString tag) {
qDebug("ScreensFactory create");
if (tag == SPLASH_TAG) {
return new SplashFragment;
} else if (tag == START_TAG) {
return new StartFragment;
} else if (tag == LOGIN_TAG) {
return new LoginFragment;
} else if (tag == REGISTRATION_TAG) {
// .....
}
}
QString ScreensFactory::createStart() {
return SPLASH_TAG; // .
}
, , , . QStackedWidget .
:
navigateTo(tag) — .
back() — .
replace(tag) — .
newRootScreen(tag) — .
navigateToWhithData(tag, data) — , navigateTo(tag), - .
, , , navigateTo(REGISTRATION_TAG), , . newRootScreen(MAIN_TAG).
, , BaseFragment , .
class BaseFragment: public QFrame {
Q_OBJECT
signals:
//
void back();
void navigateTo(QString tag);
void newRootScreen(QString tag);
void replace(QString tag);
void navigateWhithData(QString tag, BaseModel* model);
public:
BaseFragment();
~BaseFragment();
//
virtual void onPause();
virtual void onResume();
virtual void setData(BaseModel* model);
};
, , , onPause(), , onResume() , . setData() .
. QStackedWidget BaseScreensFactory .
navigator.h:
class Navigator: public QObject {
Q_OBJECT
private:
QStackedWidget *currentContainer;
BaseScreensFactory *screensFactory;
QLinkedList<BaseFragment*> stack;
/**
* @brief createAndConnect
* @param tag .
*
*
* .
*
* @return .
*/
BaseFragment* createAndConnect(QString tag);
/**
* @brief connectFragment
* @param fragment
* .
*
*
*
* .
*
*/
void connectFragment(BaseFragment *fragment);
/**
* @brief disconnectFragment
* @param fragment
*
* .
*/
void disconnectFragment(BaseFragment *fragment);
public:
Navigator(
QStackedWidget *container,
BaseScreensFactory *screensFactory
);
~Navigator();
BaseFragment* getStartScreen();
public slots:
/**
* @brief navigateTo
* @param tag .
*
* .
*/
void navigateTo(QString tag);
/**
* @brief back
*
* .
*/
void back();
/**
* @brief replace
* @param tag
* .
*
*
* .
*/
void replace(QString tag);
/**
* @brief newRootScreen
* @param tag
* .
*
*
* .
*/
void newRootScreen(QString tag);
/**
* @brief navigateWhithData
* @param model
*
* navigateTo .
*/
void navigateWhithData(QString tag, BaseModel* model);
};
. . . connectFragment , . disconnectFragment . createAndConnect . getStartScreen , , .
BaseFragment* Navigator::getStartScreen() {
return createAndConnect(this->screensFactory->createStart());
}
void Navigator::connectFragment(BaseFragment *fragment) {
connect(fragment, &BaseFragment::back, this, &Navigator::back);
connect(fragment, &BaseFragment::replace, this, &Navigator::replace);
connect(fragment, &BaseFragment::navigateTo, this, &Navigator::navigateTo);
connect(fragment, &BaseFragment::newRootScreen, this, &Navigator::newRootScreen);
connect(fragment, &BaseFragment::navigateWhithData, this, &Navigator::navigateWhithData);
}
void Navigator::disconnectFragment(BaseFragment *fragment) {
disconnect(fragment, &BaseFragment::back, this, &Navigator::back);
disconnect(fragment, &BaseFragment::replace, this, &Navigator::replace);
disconnect(fragment, &BaseFragment::navigateTo, this, &Navigator::navigateTo);
disconnect(fragment, &BaseFragment::newRootScreen, this, &Navigator::newRootScreen);
disconnect(fragment, &BaseFragment::navigateWhithData, this, &Navigator::navigateWhithData);
}
BaseFragment* Navigator::createAndConnect(QString tag) {
BaseFragment *fragment = this->screensFactory->create(tag);
connectFragment(fragment);
return fragment;
}
, .
Navigator::Navigator(
QStackedWidget *container,
BaseScreensFactory *screensFactory
) {
this->screensFactory = screensFactory;
this->currentContainer = container;
BaseFragment* startFragment = getStartScreen();
this->stack.append(startFragment);
currentContainer->addWidget(stack.last());
currentContainer->setCurrentIndex(0);
}
. : navigateTo. , . .
void Navigator::navigateTo(QString tag) {
BaseFragment *newFragment = this->screensFactory->create(tag);
stack.last()->onPause();
disconnectFragment(stack.last());
connectFragment(newFragment);
stack.append(newFragment);
currentContainer->addWidget(newFragment);
currentContainer->setCurrentWidget(newFragment);
}
, . , . .
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
try {
container = new QStackedWidget;
this->factory = new ScreensFactory;
this->navigator = new Navigator(
this->container,
this->factory
);
this->setCentralWidget(container);
} catch (std::exception& e) {
qDebug("%s", e.what());
}
}
Jetzt haben wir uns eine große Anzahl von Codeteilen angesehen. Auf den ersten Blick scheint es, dass sie nicht sehr miteinander verbunden sind. Nach vielen Versuchen, es herauszufinden, verschwindet dieses Gefühl nicht, und das ist eigentlich eine gute Sache. Infolgedessen konnten wir verschiedene Bildschirme der Anwendung völlig unabhängig von den übrigen Teilen entwickeln. Wir schreiben die BaseFragment- Implementierung und fügen sie der Factory hinzu.
Meine Lösung hat mir bei der Umsetzung des Projekts sehr geholfen. Ich konnte die Entwicklung beschleunigen und den Code aufteilen.
Vielen Dank an alle, die gelesen haben, ich hoffe, dass dies jemandem helfen wird.
Hier ist der GitHub-Link des Projekts