Qt 模型/视图/控制器示例

本文介绍了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 之类的模型和类,它可能很复杂——而不是简单的 QString 列表或保证更直接的东西.当我浏览与 MVC 相关的 Qt 文档时,我遇到了很多使用 setModel() 函数尝试建立连接的示例,我在列表项 1 和 2 中基本上概述了这些连接.问题是我看不到一种方法可以使用更复杂的数据类型(如 Game)使用这种精确方法,它可能是完整应用程序的整个数据模型(我知道 Gamecode> 在此示例中并不复杂,但最终可能会如此).我需要一些可扩展和可扩展的东西,它适用于整个应用程序.如果那些 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()));
}

ma​​inwindow.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

ma​​inwindow.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));
}

ma​​in.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.

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

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 模型/视图/控制器示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2

admin_action_{$_REQUEST[‘action’]}

do_action( "admin_action_{$_REQUEST[‘action’]}" )动作钩子::在发送“Action”请求变量时激发。Action Hook: Fires when an ‘action’ request variable is sent.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$_REQUEST['action']引用从GET或POST请求派生的操作。源码(Source)更新版本源码位置使用被使用2.6.0 wp-admin/admin.php:...

日期:2020-09-02 17:44:16 浏览:1168

admin_footer-{$GLOBALS[‘hook_suffix’]}

do_action( "admin_footer-{$GLOBALS[‘hook_suffix’]}", string $hook_suffix )操作挂钩:在默认页脚脚本之后打印脚本或数据。Action Hook: Print scripts or data after the default footer scripts.目录锚点:#说明#参数#源码说明(Description)钩子名的动态部分,$GLOBALS['hook_suffix']引用当前页的全局钩子后缀。参数(Parameters)参数类...

日期:2020-09-02 17:44:20 浏览:1069

customize_save_{$this->id_data[‘base’]}

do_action( "customize_save_{$this-&gt;id_data[‘base’]}", WP_Customize_Setting $this )动作钩子::在调用WP_Customize_Setting::save()方法时激发。Action Hook: Fires when the WP_Customize_Setting::save() method is called.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_data...

日期:2020-08-15 15:47:24 浏览:806

customize_value_{$this->id_data[‘base’]}

apply_filters( "customize_value_{$this-&gt;id_data[‘base’]}", mixed $default )过滤器::过滤未作为主题模式或选项处理的自定义设置值。Filter Hook: Filter a Customize setting value not handled as a theme_mod or option.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_date['base'],指的是设置...

日期:2020-08-15 15:47:24 浏览:898

get_comment_author_url

过滤钩子:过滤评论作者的URL。Filter Hook: Filters the comment author’s URL.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/comment-template.php:32610...

日期:2020-08-10 23:06:14 浏览:930

network_admin_edit_{$_GET[‘action’]}

do_action( "network_admin_edit_{$_GET[‘action’]}" )操作挂钩:启动请求的处理程序操作。Action Hook: Fires the requested handler action.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$u GET['action']引用请求的操作的名称。源码(Source)更新版本源码位置使用被使用3.1.0 wp-admin/network/edit.php:3600...

日期:2020-08-02 09:56:09 浏览:876

network_sites_updated_message_{$_GET[‘updated’]}

apply_filters( "network_sites_updated_message_{$_GET[‘updated’]}", string $msg )筛选器挂钩:在网络管理中筛选特定的非默认站点更新消息。Filter Hook: Filters a specific, non-default site-updated message in the Network admin.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分$_GET['updated']引用了非默认的...

日期:2020-08-02 09:56:03 浏览:863

pre_wp_is_site_initialized

过滤器::过滤在访问数据库之前是否初始化站点的检查。Filter Hook: Filters the check for whether a site is initialized before the database is accessed.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/ms-site.php:93910...

日期:2020-07-29 10:15:38 浏览:833

WordPress 的SEO 教学:如何在网站中加入关键字(Meta Keywords)与Meta 描述(Meta Description)?

你想在WordPress 中添加关键字和meta 描述吗?关键字和meta 描述使你能够提高网站的SEO。在本文中,我们将向你展示如何在WordPress 中正确添加关键字和meta 描述。为什么要在WordPress 中添加关键字和Meta 描述?关键字和说明让搜寻引擎更了解您的帖子和页面的内容。关键词是人们寻找您发布的内容时,可能会搜索的重要词语或片语。而Meta Description则是对你的页面和文章的简要描述。如果你想要了解更多关于中继标签的资讯,可以参考Google的说明。Meta 关键字和描...

日期:2020-10-03 21:18:25 浏览:1719

谷歌的SEO是什么

SEO (Search Engine Optimization)中文是搜寻引擎最佳化,意思近于「关键字自然排序」、「网站排名优化」。简言之,SEO是以搜索引擎(如Google、Bing)为曝光媒体的行销手法。例如搜寻「wordpress教学」,会看到本站的「WordPress教学:12个课程…」排行Google第一:关键字:wordpress教学、wordpress课程…若搜寻「网站架设」,则会看到另一个网页排名第1:关键字:网站架设、架站…以上两个网页,每月从搜寻引擎导入自然流量,达2万4千:每月「有机搜...

日期:2020-10-30 17:23:57 浏览:1308