2012-11-16 153 views
8

我剛剛開始使用Qt,並嘗試獲得模型 - 視圖 - 控制器設計模式的簡化工作示例。Qt模型/視圖/控制器示例

到目前爲止,我已經能夠使用信號和插槽來將基本小部件(如按鈕)連接到QLabel,並且可以在點擊/釋放按鈕時修改視圖。請參閱下面的代碼,瞭解其中的一個工作示例(在MainWindow類中實現)。

我想要定義一個類,在這種情況下,這將是我的模型,Game。我想要Game擁有我整個應用程序的所有數據和業務規則。我不要求Game是任何Qt特定的 - 它可以是通用的C++。但是,在下面的代碼中,它確實有一些Qt特定的代碼來實現QTimer,這對於本示例而言非常有用。

我想實現兩件事情在這個例子:

  1. 我想有一個模型,它能夠在自身內產生某種事件,如超過時間的推移遞增變量值,然後最終看到這種變化反映在視圖中。或者更好的是,QTimertimeout()可能只是連接到某個插槽的信號,該插槽是模型內發生的某個事件。使用下面顯示的代碼,視圖中的反射將是label_1MainWindow類的一部分)的設置,以顯示已存儲在imageOnimageOff(也是MainWindow類的一部分)中的圖像之一。
  2. 我希望與on_pushButton_clicked()on_pushButton_pressed()插槽相關聯的按鈕能夠修改存儲在模型中的某些值。然後,第1項即將到來,將模型的更新反映在視圖中。

如果我的術語到目前爲止是不正確的或與MVC設計模式的Qt術語不一致,請原諒我。我希望對此做出任何澄清。另外,如果我提供的示例代碼過於複雜,以此來舉例說明Qt中的MVC設計模式,那麼我更願意清理乾淨的頁面,並以更合適的示例開始。我所要做的就是開始使用Qt和MVC,但以一種處理更復雜的數據類型的方式。

我想開發一個例子,我可以處理一個模型和類,如Game這可能是複雜的 - 不是一個簡單的QStrings列表或保證更直接的東西。當我瀏覽與MVC相關的Qt文檔時,我遇到了很多使用setModel()函數來嘗試和建立連接的例子,我基本上列出了列表項目1和2.問題是我看不到方法對於更復雜的數據類型(如Game),可能是完整應用程序的整個數據模型(我知道Game在這個例子中並不複雜,但最終可能是這樣)。我需要一些可擴展和可擴展的東西,這些東西可以用於整個應用程序。如果那些setModel()類型的函數適用於此 - 他們很可能會是這樣,我只是無法自己弄清楚 - 我想知道如何實現在這個例子中處理QLabel和圖像。

代碼:

遊戲。ħ

#ifndef GAME_H 
#define GAME_H 

#include <QtCore> 

class Game : public QObject { 

    Q_OBJECT 

public: 
    Game(); 
    void timed_job(); 

private: 
    QTimer *timer; 
}; 

#endif // GAME_H 

game.cpp

#include "game.h" 
#include <QtCore> 

Game::Game() { 
} 

void Game::timed_job() { 
    timer = new QTimer(this); 
    timer->start(1000); 
    //connect(timer, SIGNAL(timeout()), this, SLOT(flip())); 
} 

mainwindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 

namespace Ui { 
    class MainWindow; 
} 

class MainWindow : public QMainWindow { 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private slots: 
    void on_pushButton_clicked(); 
    void on_pushButton_pressed(); 

private: 
    Ui::MainWindow *ui; 
    QImage imageOn, imageOff; 
}; 

#endif // MAINWINDOW_H 

mainwindow.cpp

Qt中

的main.cpp

#include <QtGui/QApplication> 
#include <QLabel> 
#include "mainwindow.h" 
#include "game.h" 

int main(int argc, char *argv[]) { 
    QApplication a(argc, argv); 

    MainWindow w; 

    w.show(); 

    return a.exec(); 
} 
+0

Qt使用模型視圖方法,沒有單獨的控制器。你想使用Qt模型視圖的東西,或者推出自己的MVC的東西?那麼,真正的問題是什麼? – hyde

+0

我不知道Qt model-view的成本和收益與我自己的MVC有什麼關係,但是我看不到任何理由爲了這個目的而對穀物進行工作。我想這意味着我想使用Qt模型視圖的東西。我並不想強制控制器加入混合。我不知道Qt本身不是獨特的控制器。 – nairware

+0

一般的看法(從我讀過的)可以看出,便利小部件適合小東西。視圖/標準模型非常適用於需要擁有一個數據模型和許多相同數據的視圖......並且最後...如果您需要執行代表您自己的數據結構的大型數據集,那麼定製模型就在那裏這種表現。 – jdi

回答

7

「控制器」 可以在技術上由一個單獨的子類QObject來表示,含有時隙。你可以在你的模型和視圖之間連線。
但通常我所做的(和看到的)只是讓您的模型包含業務邏輯,而您的視圖子類包含處理它的用戶交互的方法。最接近控制器概念的是當我有代表應用程序的QMainWindow(或對話框)類時,並且它有一堆SLOTS。這些插槽連接到私有UI成員信號以將它們連接在一起。

例如:您的主窗口有一個模型,一個視圖和一個按鈕。在主窗口的init中,我將在視圖中設置模型,並將按鈕「clicked」連接到我的窗口上的插槽refreshData()。然後該槽將調用模型上的「更新」方法,該方法將自動傳播到視圖。主窗口就像一個控制器。

你想要做的是做一些QAbstractItemModelQStandardItemModel代表你的數據並做你想要更新的數據(像你建議的計時器)。由於標準接口,連接到模型的任何視圖都能夠看到它。你也可以進行單獨的計時器,數據放置到現有QStandardItemModel

的注意事項有關自定義化QAbstractItemModel類

正如@hyde指出,跳進一個自定義模式可以是一個挑戰,如果你嘗試首先要做的是在對現有的具體模型類有一個很好的理解之前。以下是我建議這樣做:

  1. 熟悉的便利的小部件(QListWidget,QTableWidget的,QTreeWidget)
  2. 然後使用QStandardItemModel用而QListView/QTableView中
  3. 嘗試再與QTreeView則
  4. 最後工作,當你真的需要爲你現有的數據結構進行非常自定義的建模時,你可以使用子類化QAbstractItemModel來使它使用你自己的內部結構。
+2

關於QAbstractItemModel的一個評論:它可以說是最複雜的部分之一Qt,所以最好準備一些頭髮拉動,並仔細閱讀文檔,從頭開始做第一個模型... – hyde

+0

這可能只是一種主觀的體驗。如果您在不瞭解現有的具體模型的情況下立即着手,那就很複雜。一旦你知道這些工作是如何工作的,獲得一個簡單的只讀自定義模型就很容易了。儘管我會更新一些信息。謝謝! – jdi

+0

感謝您的待辦事項。我將開始着手,並以更好的基礎回來。 – nairware