Qtでナビゲーションを書く

みなさん、こんにちは。私は経験の少ないAndroid開発者です。そして今日は、画面間の簡単なナビゲーションを使用してC ++Qt教育プロジェクトを開発した経験を共有したいと思います。私の解決策に対する批判や追加を聞いてうれしく思います。それが誰かを助け、人生を楽にしてくれることを願っています。





仕事

始める前に、最終的に混乱が生じないように2つの用語を定義しましょう。

ウィンドウは、ウィンドウまたはその他のOSで最も一般的なウィンドウです。

画面-ウィンドウ内で他のコンテンツに置き換えることができるある種のコンテンツ。





, - Trello, , . ? , .





, , QStackedWidget . - .





. , , . .





, , , :





  1. .





  2. .





  3. .





  4. .





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();
};

      
      



:





  1. create(QString tag) — ( );





  2. 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());
    }
}
      
      



これで、多数のコードを調べましたが、最初は、それらがあまり接続されていないように見える場合があります。何度も考えてみても、この気持ちは消えませんし、実はいいことです。その結果、他の部分とは完全に独立して、アプリケーションのさまざまな画面を開発することができました。BaseFragment実装を作成し、ファクトリに追加します。





私のソリューションは、プロジェクトの実装に大いに役立ちました。開発をスピードアップし、コードを分割することができました。





読んだすべての人に感謝します。これが誰かの助けになることを願っています。





これがプロジェクトのGitHubリンクです








All Articles