15

私はQtを始めたばかりで、model-view-controllerデザインパターンの単純化された実用的な例を取得しようとしています。

これまでのところ、シグナルとスロットを使用して、プッシュボタンなどの基本的なウィジェットをに接続QLabelし、プッシュボタンがクリック/リリースされるとビューを変更することができました。その実用的な例については、以下のコードを参照してください(MainWindowクラスで実装されています)。

私はクラスを定義しようとしています。この場合はGame、これが私のモデルになります。Gameアプリケーション全体のすべてのデータとビジネスルールが必要です。私はそれがQt固有のものである必要はありませんGame-それは一般的なC++である可能性が非常に高いです。QTimerただし、以下のコードには、この例の目的に役立つを実装するためのQt固有のコードがいくつか含まれています。

この例では、次の2つのことを達成しようとしています。

  1. 時間の経過とともに変数値をインクリメントするなど、それ自体の中で何らかのイベントを生成し、最終的にその変更がビューに何らかの形で反映されることを確認できるモデルが必要です。またはさらに良いことtimeout()に、のQTimerは単にいくつかのスロットに接続されている信号である可能性があり、そのスロットはモデル内で発生するイベントです。以下に示すコードを使用すると、ビューでの反射は、または(クラスの一部)にすでに保存されている画像の1つを表示するためのlabel_1(クラスの一部)の設定になります。MainWindowimageOnimageOffMainWindow
  2. on_pushButton_clicked()とスロットに関連付けられたプッシュボタンon_pushButton_pressed()で、モデル内に保存されている値を変更できるようにしたい。次に、項目1を完全に一周して、モデルの更新をビューに反映させます。

これまでの私の用語が正しくないか、MVCデザインパターンのQt用語と矛盾している場合は、ご容赦ください。それについての説明を歓迎します。また、私が提供したサンプルコードが複雑すぎて、QtのMVCデザインパターンを例示できない場合は、スレートをきれいに拭き取り、より適切な例から始めたいと思います。私がやろうとしているのは、QtとMVCを使い始めることだけですが、より複雑なデータ型を扱う方法で。

私は、Game潜在的に複雑なモデルやクラスを処理できる例を開発しようとしています。QStringの単純なリストや、より単純であることが保証されているものではありません。setModel()MVCに関連するQtのドキュメントを閲覧すると、この関数を使用して、リスト項目1と2で基本的に概説している接続を試行する多くの例に出くわしました。問題は、Game完全なアプリケーションのデータモデル全体である可能性があるような、より複雑なデータ型でその正確なアプローチを使用します(Gameこの例では複雑ではないことはわかっていますが、最終的には複雑になる可能性があります)。スケーラブルで拡張可能なもの、アプリケーション全体で機能するものが必要です。それらの場合setModel()-タイプの関数はこれに適しています-おそらくそうかもしれませんが、私はそれを自分で理解することはできませんでした-この例QLabelで画像を扱うそれらを実装する方法を知りたいです。

コード:

game.h

#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

#include <QImage>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow) {
    imageOn.load(":/Files/On.jpg");
    imageOff.load(":/Files/Off.jpg");

    ui->setupUi(this);
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::on_pushButton_clicked() {
    ui->label_1->setPixmap(QPixmap::fromImage(imageOff));
}

void MainWindow::on_pushButton_pressed() {
    ui->label_1->setPixmap(QPixmap::fromImage(imageOn));
}

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

1 に答える 1

10

Qtの「コントローラー」は、技術的にはスロットのみを含む別のQObjectサブクラスで表すことができます。そして、これをモデルとビューの間に配線します。
しかし、通常、私が行う(そして見る)のは、モデルにビジネスロジックを含めることであり、ビューサブクラスにはそのユーザーインタラクションを処理するためのメソッドが含まれます。コントローラの概念に最も近いのは、アプリケーションを表すQMainWindow(またはダイアログ)クラスがあり、その上に多数のSLOTSがある場合です。これらのスロットは、プライベートUIメンバーの信号に接続され、それらを相互に接続します。

例:メインウィンドウには、モデル、ビュー、およびプッシュボタンがあります。メインウィンドウの初期化では、ビューにモデルを設定し、「クリックした」プッシュボタンをウィンドウのスロットに接続しますrefreshData()。次に、このスロットはモデルの「update」メソッドを呼び出し、ビューに自動的に伝播します。したがって、メインウィンドウはコントローラーのように機能します。

あなたがしたいことは、あなたのデータを表すある種のQAbstractItemModelまたはQStandardItemModelそれを作り、あなたがそのデータを更新したいことをすることです(あなたが提案したようなタイマー)。標準のインターフェースにより、モデルに接続されているすべてのビューでモデルを表示できます。また、既存のデータにデータを配置する別のタイマーを作成することもできます QStandardItemModel

カスタムQAbstractItemModelクラスに関する注意

@hydeが指摘しているように、カスタムモデルにジャンプすることは、既存の具象モデルクラスを十分に理解する前に、最初に試してみると難しい場合があります。これが私がすることをお勧めすることです:

  1. 便利なウィジェット(QListWidget、QTableWidget、QTreeWidget)に慣れてください
  2. 次に、QListView/QTableViewでQStandardItemModelを使用してみてください
  3. 次に、QTreeViewを使用します
  4. 最後に、既存のデータ構造に対して非常にカスタムなモデリングが本当に必要な場合は、QAbstractItemModelをサブクラス化して、独自の内部構造を使用できるようにすることができます。
于 2012-11-16T19:38:36.487 に答える