Qt的模型/视图/控制器示例(Qt Model/View/Controller Example)

2019-07-03 21:13发布

我刚刚开始使用Qt,并试图获得模型 - 视图 - 控制器设计模式的简化,工作示例。

到目前为止,我已经能够使用信号和槽,以基本部件连接如按钮到QLabel ,并且具有作为按钮被点击的视图中修改/释放。 对于该工作示例(在实施见下文代码MainWindow类)。

我试图定义一个类,在这种情况下, Game ,这将是我的模型。 我希望Game有我所有的整个应用程序的数据和业务规则。 我不要求Game是什么Qt的具体-这非常好可能是通用的C ++。 然而,在下面的代码,它确实有一些具体的Qt的代码来实现QTimer这是这个例子的目的。

我想实现两件事情在这个例子:

  1. 我想有一个模型,它能够在自身内产生某种事件,如超过时间的推移递增变量值,然后最终看到的变化在某种程度上反映在视图。 或者更好的是,在timeout()中的QTimer可以简单地连接到某些插槽的信号,该插槽是一些事件都是在模型内进行。 使用如下所示的代码中,在视图中的反射将是设定label_1 (的部分MainWindow类),显示已经存储在图像中的一个imageOnimageOff (也是部分MainWindow类)。
  2. 我想有相关按钮on_pushButton_clicked()on_pushButton_pressed()插槽能够修改存储在模型内的一些价值。 然后,一圈下来与第1项,有模型的该更新在视图中反映出来。

如果我的术语迄今不正确,或与MVC设计模式的Qt的术语不一致,请原谅我。 我欢迎任何澄清。 另外,如果我所提供的示例代码是Qt中举例说明MVC设计模式太绕口,我更愿意彻底清除,并用一个更合适的例子开始更多。 所有我想要做的是开始使用Qt和MVC,但在更复杂的数据类型的交易方式。

我想开发,我可以处理模型,类如例如Game这是潜在的复杂-保证更直接的将QString什么的不是一个简单的列表。 当我通过与MVC Qt文档浏览,我遇到了很多的例子,所使用的来到setModel()函数,试图让我基本上是列表中的项目概述连接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();
}

Answer 1:

在Qt的“控制器”可以在技术上由单独表示QObject亚类中,含有时隙。 而你也连线该模型和视图之间。
但通常我做什么(看)是只让你的模型包含业务逻辑,而您的视图子类包含用于处理它的用户交互的方法。 我到控制器概念最接近的是,当我有代表应用程序我的QMainWindow(或对话框)类,并有一堆关于它插槽。 这些插槽得到有线到私有UI成员信号将它们连接在一起。

例如:你的主窗口有一个模型,视图和按钮。 在init主窗口,我会设定在视图模型,并连接我的窗口上的按钮“点击”发送插槽refreshData() 然后,该槽将要求在模型上,这将自动地传播到视图中的“更新”的方法。 主窗口从而就像一个控制器。

什么,你会想要做的是使一些类型QAbstractItemModelQStandardItemModel代表您的数据,但要更新数据(像你这样的计时器的建议)是什么。 连接到模型的任何视图可以看到,因为标准接口的它。 你也可以进行单独的计时器,数据放置到现有QStandardItemModel

有关自定义化QAbstractItemModel类的注意事项

正如@hyde指出,跳进一个自定义模式可以是一个挑战,如果你尝试先去做,让现有的混凝土模型类有很好的理解了。 以下是我建议这样做:

  1. 熟悉的便利的小部件(QListWidget,QTableWidget的,QTreeWidget)
  2. 然后尝试使用QStandardItemModel用而QListView / QTableView中
  3. 然后用QTreeView则工作
  4. 最后,当你真的需要为您现有的数据结构非常定制造型,你可以在子类化QAbstractItemModel工作,使其使用自己的内部结构。


文章来源: Qt Model/View/Controller Example