Qt模型/视图/控制器示例 [英] Qt Model/View/Controller Example

查看:76
本文介绍了Qt模型/视图/控制器示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am just getting started in Qt, and trying to get a simplified, working example of the model-view-controller design pattern.

到目前为止,我已经能够使用信号和插槽将诸如按钮之类的基本小部件连接到QLabel,并且可以在单击/释放按钮时修改视图.参见下面的代码,了解该示例的工作示例(在MainWindow类中实现).

So far, I have been able to use signals and slots to connect basic widgets like push buttons to a QLabel, and have the view be modified as the push button is clicked/released. See code below for a working example of that (implemented in the MainWindow class).

我正在尝试定义一个类,在这种情况下为Game,它将作为我的模型.我希望Game拥有整个应用程序的所有数据和业务规则.我不要求Game是Qt特有的任何东西-它很可能是通用C ++.但是,在下面的代码中,它确实具有一些Qt特定的代码来实现QTimer,这对于本示例而言非常有用.

I am trying to define a class, in this case, Game, which is going to be my model. I want Game to have all of the data and business rules of my entire application. I do not require that Game be anything Qt specific--it very well could be generic C++. However, in the code below, it does have some Qt-specific code to implement a QTimer which is useful for the purposes of this example.

在此示例中,我试图实现两件事:

I am trying to achieve two things in this example:

  1. 我希望有一个能够在自身内部生成某种事件的模型,例如随着时间的推移增加变量值,然后最终以某种方式在视图中反映出这种变化.更好的是,QTimertimeout()可以只是连接到某个插槽的信号,该插槽是模型内发生的某种事件.使用下面显示的代码,视图中的反射将是label_1的设置(MainWindow类的一部分),以显示已经存储在imageOnimageOff中的图像之一(也是MainWindow类).
  2. 我希望与on_pushButton_clicked()on_pushButton_pressed()插槽关联的按钮能够修改模型中存储的某些值.然后,将第1项变成一个完整的圆圈,使模型的更新反映在视图中.
  1. I want to have a model which is able to generate some sort of event within itself, like incrementing a variable value over the passage of time, and then ultimately see that change somehow reflected in the view. Or better yet, the timeout() of the QTimer could simply be the signal that is connected to some slot, that slot being some event that takes place within the model. Using the code shown below, the reflection in the view would be the setting of label_1 (part of the MainWindow class) to display one of the images already stored in imageOn or imageOff (also part of the MainWindow class).
  2. I want to have the push button associated with the on_pushButton_clicked() and on_pushButton_pressed() slots be able to modify some value stored within the model. Then, coming full circle with item 1, have that update of the model be reflected in the view.

如果到目前为止我的术语不正确或与MVC设计模式的Qt术语不一致,请原谅.我欢迎对此作出任何澄清.另外,如果我提供的示例代码太复杂而无法在Qt中举例说明MVC设计模式,那么我非常愿意擦拭一切,从一个更合适的示例开始.我要做的只是从Qt和MVC入手,但是要以处理更复杂的数据类型的方式开始.

If my terminology thus far is incorrect or inconsistent with Qt terminology of MVC design pattern, forgive me. I would welcome any clarification on that. Also, if the example code I have provided is too convoluted for exemplifying the MVC design pattern in Qt, I am more than willing to wipe the slate clean and start with a more appropriate example. All I am trying to do is get started with Qt and MVC, but in a way that deals with more complex data types.

我正在尝试开发一个示例,在该示例中,我可以处理可能很复杂的模型和类,例如Game,而不是简单的QStrings列表或可以保证更简单的列表.当我浏览与MVC相关的Qt文档时,遇到了很多使用setModel()函数的示例,它们试图使我基本上在列表项1和2中概述了这些连接.问题是我看不到一种对更复杂的数据类型(例如Game)使用精确方法的方法,该数据类型可能是完整应用程序的整个数据模型(我知道Game在此示例中并不复杂,但最终可能是复杂的).我需要具有可伸缩性和可扩展性的东西,并且这些东西可以在整个应用程序中使用.如果那些setModel()类型的函数适合于此(很可能是这样,我只是靠自己无法解决),我想知道如何在此示例中实现那些处理QLabel的函数和图像.

I am trying to develop an example in which I can handle a model and class such as Game which is potentially complex--not a simple list of QStrings or something guaranteed to be more straight-forward. When I browsed through the Qt documentation related to MVC, I came across a lot of examples that used the setModel() function to try and make the connections I am essentially outlining in list items 1 and 2. The problem was that I could not see a way of using that exact approach with a more complex data-type like Game which might be the entire data model for a complete application (I know Game is not complex in this example, but it could be eventually). I need something that is scalable and extensible, something that would work for an entire application. If those setModel()-type functions are suitable for this--which they very likely could be, I just could not figure it out on my own--I would like to know how to implement those in this example dealing with QLabel and images.

代码:

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

推荐答案

从技术上讲,Qt中的控制器"可以由单独的QObject子类表示,仅包含插槽.然后将其连接到模型和视图之间.
但是通常,我要做的(就是看到的)只是使您的模型包含业务逻辑,而您的视图子类包含处理其用户交互的方法.我最接近控制器的概念是当我有代表应用程序的QMainWindow(或对话框)类,并且上面有很多SLOTS时.这些插槽连接到专用UI成员信号中,以将它们连接在一起.

A "controller" in Qt could technically be represented by a separate QObject subclass, containing just slots. And you would wire this between your model and view.
But normally what I do (and see) is to just make your model contain business logic, and your view subclass contain methods for handling it's user interactions. The closest I get to the controller concept is when I have my QMainWindow (or dialog) class that represents the application, and has a bunch of SLOTS on it. These slots get wired in to the private UI members signals to connect them together.

示例:您的主窗口有一个模型,一个视图和一个按钮.在主窗口的初始化中,我将在视图中设置模型,然后将单击"按钮连接到窗口refreshData()上的插槽.然后,该插槽将在模型上调用"update"方法,该方法将自动传播到视图.因此,主窗口就像控制器一样.

Example: Your main window has a model, a view, and a push button. In the init for the main window, I would set the model in the view, and connect the push button "clicked" to a slot on my window refreshData(). This slot would then call the "update" method on the model, which will automatically propagate to the view. The main window thus acts like a controller.

您想要做的是制作某种表示您的数据的QAbstractItemModelQStandardItemModel类型,并做您想更新的数据(如您建议的计时器).由于标准界面,连接到模型的任何视图都将能够看到它.您也可以制作一个单独的计时器,将数据放入现有的QStandardItemModel

What you would want to do is to make some type of QAbstractItemModel or QStandardItemModel that represents your data and does what you want to update that data (a timer like you suggested). Any view connected to the model will be able to see it because of the standard interface. You can also just make a separate timer that places data into an existing QStandardItemModel

有关自定义QAbstractItemModel类的说明

正如@hyde所指出的那样,如果要先尝试做一个自定义模型,那么在对现有的具体模型类有一个很好的了解之前,要进入一个自定义模型可能是一个挑战.我建议这样做:

As pointed out by @hyde, jumping into a custom model can be a challenge if you try and do it first, before getting a good understanding of the existing concrete model classes. Here is what I recommend doing:

  1. 熟悉便利小部件(QListWidget,QTableWidget,QTreeWidget)
  2. 然后尝试将QStandardItemModel与QListView/QTableView一起使用
  3. 然后使用QTreeView
  4. 最后,当您确实确实需要对现有数据结构进行非常自定义的建模时,可以对QAbstractItemModel进行子类化,以使其使用您自己的内部结构.

这篇关于Qt模型/视图/控制器示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆