Halo semuanya. Saya seorang pengembang android dengan sedikit pengalaman. Dan hari ini saya ingin berbagi pengalaman mengembangkan proyek pendidikan dalam C ++ dan Qt dengan navigasi sederhana antar layar. Saya akan senang mendengar kritik atau tambahan pada solusi saya dan saya berharap ini dapat membantu seseorang dan membuat hidup lebih mudah.
Tugas
Sebelum kita mulai, mari kita definisikan dua istilah agar pada akhirnya tidak ada kebingungan.
Jendela adalah jendela paling umum di jendela atau os lainnya.
Layar - beberapa jenis konten yang dapat diganti oleh orang lain di dalam jendela.
, - 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());
}
}
Sekarang kita telah melihat sejumlah besar kode, pada awalnya mungkin tampak bahwa mereka tidak terlalu terhubung. Setelah banyak mencoba mencari tahu, perasaan ini tidak hilang, dan ini sebenarnya adalah hal yang baik. Hasilnya, kami dapat mengembangkan berbagai layar aplikasi sepenuhnya secara independen dari bagian lainnya. Kami menulis implementasi BaseFragment dan menambahkannya ke pabrik.
Solusi saya banyak membantu saya dalam implementasi proyek. Saya dapat mempercepat pengembangan dan membagi kode.
Terima kasih untuk semua yang telah membaca, saya harap ini akan membantu seseorang.
Berikut adalah tautan GitHub dari proyek tersebut