项目视图组(基于模型)Model-Based
Model-Based
(1)List View:清单视图
QListView
-
继承关系:继承自 QAbstractItemView,被 QListWidget 和 QUndoView 继承
-
功能:提供模型上的列表或图标视图,以非分层列表或图标集合形式显示模型中的项
-
历史替代:替代了以前由 QListBox 和 QIconView 提供的列表和图标视图
-
区别:QListView 基于模型(Model),减少冗余数据,提高效率;QListWidget 是基于项(Item)的,封装了 QListView 的模型,操作更方便
-
常用的Qt数据模型
-
QStringListModel:用于存储简单的 QString 列表
-
QStandardItemModel:用于管理复杂的树型结构数据项,每个项都可以包含任意数据
-
QDirModel:提供本地文件系统中的文件和目录信息
-
QSqlQueryModel、QSqlTableModel、QSqlRelationTableModel:用于访问和操作数据库
-
-
(2)Tree View:树形视图
QTreeView
-
继承关系:继承自 QAbstractItemView,被 QTreeWidget 继承
-
功能:提供树视图的默认模型/视图实现,用于表示模型项的树结构
-
用途:替代以前由 QListView 提供的标准分层列表,利用更灵活的模型/视图结构
用法示例
-
要使一个 QTreeView 能够显示数据,需要
构造一个 model 并设置 QTreeView。Qt 提供了一些类型的 Model,其中最常用的就是这个
QStandardItemModel 类,一般可以满足大部分需求。另外,表头的内容也由这个 model 管理,
setHorizontalHeaderLabels 函数可以设置共有多少列、每列文字。一级标题直接使用 appendRow
方法添加到 model 上,次级标题则是添加到第一个父级标题上,依次构成父子关系树 -
新建例程中不要勾选“Generate form”,默认继承 QMainWindow 类即可
-
mainwindow.h
- 1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include
5 #include
6
7 class MainWindow : public QMainWindow
8{
9 Q_OBJECT
10
11 public:
12 MainWindow(QWidget *parent = nullptr);
13 ~MainWindow();
14
15 private:
16 QTreeView *treeView;
17
18 };
19 #endif // MAINWINDOW_H
- 1 #ifndef MAINWINDOW_H
-
mainwindow.cpp
- 1 #include “mainwindow.h”
2
3 #include
4 #include
5
6 MainWindow::MainWindow(QWidget parent)
7 : QMainWindow(parent)
8{
9 / 设置窗口的位置与大小 /
10 this->setGeometry(0, 0, 800, 480);
11 / 实例化 QTreeView 对象 /
12 treeView = new QTreeView(this);
13 / 居中 /
14 setCentralWidget(treeView);
15
16 / 构建 Model /
17 QStandardItemModel sdiModel = new QStandardItemModel(treeView);
18 sdiModel->setHorizontalHeaderLabels(
19 QStringList()<<QStringLiteral(“标题”)
20 << QStringLiteral(“名称”)
21 );
22
23 for(int i = 0; i < 5; i++) {
24 / 一级标题 /
25 QList<QStandardItem> items1;
26 QStandardItem item1 =
27 new QStandardItem(QString::number(i));
28 QStandardItem* item2 =
29 new QStandardItem(QStringLiteral(“一级标题”));
30 /* 添加项一 /
31 items1.append(item1);
32 / 添加项二 /
33 items1.append(item2);
34 / appendRow 方法添加到 model 上 /
35 sdiModel->appendRow(items1);
36
37 for(int j = 0; j < 5; j++) {
38 / 在一级标题后面插入二级标题 /
39 QList<QStandardItem> items2;
40 QStandardItem* item3 =
41 new QStandardItem(QString::number(j));
42 QStandardItem* item4 =
43 new QStandardItem(QStringLiteral(“二级标题”));
44 items2.append(item3);
45 items2.append(item4);
46 /* 使用 appendRow 方法添加到 item1 上 /
47 item1->appendRow(items2);
48 }
49 }
50 / 设置 Model 给 treeView */
51 treeView->setModel(sdiModel);
52 }
53
54 MainWindow::~MainWindow()
55 {
56 }
- 1 #include “mainwindow.h”
-
main.cpp
- 由新建项目时生成,无改动
运行效果
- 可以点击数字来展开二级标题
(3)Table View:表视图
QTableView
-
继承关系:继承自 QAbstractItemView,被 QTableWidget 继承
-
功能:提供表视图的默认模型/视图实现,显示来自模型的项
-
用途:用于替代以前由 QTable 类提供的标准表,采用更灵活的模型/视图结构
用法示例
-
使一个 QTableView 能够显示数据,需要构
造一个 model 并设置给 QTableView。Qt 提供了一些类型的 Model,其中最常用的就是这个
QStandardItemModel 类,一般可以满足大部分需求。另外,表头的内容也由这个 model 管理,
setHorizontalHeaderLabels 函数可以设置共有多少列、每列文字 -
在新建例程中不要勾选“Generate form”,默认继承 QMainWindow 类即可
-
mainwindow.h
- 1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include
5 #include
6
7 class MainWindow : public QMainWindow
8{
9 Q_OBJECT
10
11 public:
12 MainWindow(QWidget *parent = nullptr);
13 ~MainWindow();
14
15 private:
16 QTableView *tableView;
17 };
18 #endif // MAINWINDOW_H
- 1 #ifndef MAINWINDOW_H
-
mainwindow.cpp
- 1 #include “mainwindow.h”
2 #include
3 #include
4
5 MainWindow::MainWindow(QWidget parent)
6 : QMainWindow(parent)
7{
8 / 设置窗口的位置与大小 /
9 this->setGeometry(0, 0, 800, 480);
10 tableView = new QTableView(this);
11 setCentralWidget(tableView);
12 / 显示网格线 /
13 tableView->setShowGrid(true);
14
15 QStandardItemModel model = new QStandardItemModel();
16 QStringList labels =
17 QObject::tr(“语文,数学,英语”).simplified().split(“,”);
18 /* 设置水平头标签 /
19 model->setHorizontalHeaderLabels(labels);
20
21 / item /
22 QStandardItem item = 0;
23 /* model 插入项内容 /
24 for(int i = 0; i < 5; i++){
25 item = new QStandardItem(“80”);
26 model->setItem(i, 0, item);
27 item = new QStandardItem(“99”);
28 model->setItem(i, 1, item);
29 item = new QStandardItem(“100”);
30 model->setItem(i, 2, item);
31 }
32 / 将 model 设置给 tableView /
33 tableView->setModel(model);
34 / 平均分列 /
35 tableView->horizontalHeader()
36 ->setSectionResizeMode(QHeaderView::Stretch);
37 / 平均分行 */
38 tableView->verticalHeader()
39 ->setSectionResizeMode(QHeaderView::Stretch);
40 }
41
42 MainWindow::~MainWindow()
43 {
44 }
- 1 #include “mainwindow.h”
-
main.cpp
- 由新建项目时生成,无改动
运行效果
- 建立一个成绩表格
(4)Column View:列表视图
QColumnView
-
继承关系:继承自 QAbstractItemView
-
功能:在多个 QListView 中显示一个模型,每个 QListView 对应树的一个层次结构(级联列表)
-
用途:作为模型/视图框架的一部分,显示模型提供的数据
用法示例
-
新建例程中不要勾选“Generate form”,默认继承 QMainWindow 类即可
-
mainwindow.h
- 1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include
5 #include
6
7 class MainWindow : public QMainWindow
8{
9 Q_OBJECT
10
11 public:
12 MainWindow(QWidget *parent = nullptr);
13 ~MainWindow();
14
15 private:
16 QColumnView *columnView;
17 };
18 #endif // MAINWINDOW_H
- 1 #ifndef MAINWINDOW_H
-
mainwindow.cpp
- 1 #include “mainwindow.h”
2 #include
3
4 MainWindow::MainWindow(QWidget parent)
5 : QMainWindow(parent)
6{
7 / 设置主窗体显示位置与大小 */
8 this->setGeometry(0, 0, 800, 480);
9 QStandardItemModel model = new QStandardItemModel;
10
11 / 省份 */
12 QStandardItem province = new QStandardItem(“广东省”);
13
14 / 城市 */
15 QStandardItem *city1 = new QStandardItem(“茂名市”);
16 QStandardItem city2 = new QStandardItem(“中山市”);
17
18 / 添加城市到省份下 */
19 province->appendRow(city1);
20 province->appendRow(city2);
21
22 QStandardItem *town1 = new QStandardItem(“电白镇”);
23 QStandardItem town2 = new QStandardItem(“南头镇”);
24
25 / 添加城镇到城市下 /
26 city1->appendRow(town1);
27 city2->appendRow(town2);
28
29 columnView = new QColumnView;
30
31 / 建立 model /
32 model->appendRow(province);
33
34 / 设置 model /
35 columnView->setModel(model);
36
37 / 设置居中 */
38 setCentralWidget(columnView);
39 }
40
41 MainWindow::~MainWindow()
42 {
43 }
- 1 #include “mainwindow.h”
-
main.cpp
- 由新建项目时生成,无改动
运行效果
- 当点击省份出现城市,点击城市出现城镇
(5)Undo View:撤销列表视图
QUndoView
-
继承关系:继承自 QListView
-
功能:显示 QUndoStack 的内容,展示撤销堆栈上的命令列表
-
用途:选择不同命令以调用 QUndoStack::setIndex(),调整文档状态;可以通过 setStack() 或 setGroup() 设置堆栈或组
-
命令选择
-
总是选择最近执行的命令
-
选择不同的命令会导致调用
-
QUndoStack::setIndex(),从而将文档的状态向后或向前滚动到新的命令
-
-
用法示例
-
新建例程中不要勾选“Generate form”,默认继承 QMainWindow 类即可
-
同时添加了两个新建文件,点击新建,选择 C++》C++ Source File 命名 command.h 和 command.cpp 文件,用于重写 QUndoCommand
-
command.h
- 1 #ifndef COMMAND_H
2 #define COMMAND_H
3
4 #include
5 #include
6
7 class addCommand : public QUndoCommand
8{
9 public:
10 addCommand(int value, QUndoCommand parent = 0);
11 ~addCommand();
12
13 /* 重写重做与撤回方法 /
14 void redo() override;
15 void undo() override;
16
17 private:
18 / 新的 count */
19 int new_count;
20
21 / 旧的 count */
22 int old_count;
23 };
24
25 #endif // COMMAND_H
- 1 #ifndef COMMAND_H
-
mainwindow.h
- 1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include <command.h>
12
13 class MainWindow : public QMainWindow
14 {
15 Q_OBJECT
16
17 public:
18 MainWindow(QWidget parent = nullptr);
19 ~MainWindow();
20
21 private:
22 / 水平布局 */
23 QHBoxLayout hLayout;
24 / 水平布局 */
25 QVBoxLayout vLayout;
26 / 用于容纳 hLayout 布局 */
27 QWidget mainWidget;
28 / 容器作用 QWidget,用于容纳标签与按钮 */
29 QWidget widget;
30 / 存放 QUndoCommand 命令的栈 */
31 QUndoStack undoStack;
32 / 历史记录面板 */
33 QUndoView undoView;
34 / 用于显示计算结果 */
35 QLabel label;
36 / 按钮 */
37 QPushButton pushButton;
38 / 计算结果 */
39 int count;
40
41 private slots:
42 void pushButtonClieked();
43 void showCountValue(int);
44 };
45 #endif // MAINWINDOW_H
- 1 #ifndef MAINWINDOW_H
-
command.cpp
- 1 #include “command.h”
2 #include
3
4 addCommand::addCommand(int value, QUndoCommand parent)
5{
6 / 使用 Q_UNUSED,避免未使用的数据类型 /
7 Q_UNUSED(parent);
8
9 / undoView 显示的操作信息 /
10 setText(“进行了加 1 操作”);
11
12 / value 的地址赋值给 new_count /
13 new_count = value;
14
15 / 让构造函数传过来的new_count 的值赋值给 old_count */
16 old_count = new_count;
17 }
18
19 / 执行 stack push 时或者重做操作时会自动调用 /
20 void addCommand::redo()
21 {
22 / 重新赋值给 new_count /
23 new_count = old_count;
24
25 / 打印出new_count 的值 */
26 qDebug()<<“redo:”<<new_count<<endl;
27 }
28
29 / 回撤操作时执行 /
30 void addCommand::undo()
31 {
32 / 回撤操作每次应减一 /
33 (new_count)–;
34
35 / 打印出new_count 的值 */
36 qDebug()<<“undo:”<<*new_count<<endl;
37 }
38
39 addCommand::~addCommand()
40 {
41
42 }
- 1 #include “command.h”
-
mainwindow.cpp
- 1 #include “mainwindow.h”
2 #include
3
4 MainWindow::MainWindow(QWidget parent)
5 : QMainWindow(parent)
6{
7 / 设置主窗体显示的位置与大小 /
8 this->setGeometry(0, 0, 800, 480);
9
10 / 实例一个水平布局,用于左侧按钮区域与右侧历史记录面板 /
11 hLayout = new QHBoxLayout();
12
13 / 实例一个水平布局,用于左侧标签与按钮 /
14 vLayout = new QVBoxLayout();
15
16 / 主 Widget, 因为 MainWindow 自带一个布局,
17 * 我们要新建一个 Widget 容纳新布局
18 /
19 mainWidget = new QWidget();
20
21 / 用于存放命令行栈 /
22 undoStack = new QUndoStack(this);
23
24 / 用于容纳左侧标签与按钮布局 /
25 widget = new QWidget();
26
27 / 历史记录面板实例化 /
28 undoView = new QUndoView(undoStack);
29
30 / 实例一个按钮,用于加一操作 /
31 pushButton = new QPushButton();
32
33 / 标签,用于显示计算结果 /
34 label = new QLabel();
35
36 / 设置 widget 的大小 /
37 widget->setMinimumSize(400, 480);
38
39 / 将两个 widget 添加到水平布局 /
40 hLayout->addWidget(widget);
41 hLayout->addWidget(undoView);
42
43 / 初始化 count 的值 /
44 count = 0;
45
46 / 显示初始化计算结果 /
47 label->setText(“计算结果:” + QString::number(count));
48 label->setAlignment(Qt::AlignCenter);
49
50 / 左侧布局 /
51 vLayout->addWidget(label);
52 vLayout->addWidget(pushButton);
53
54 / 左侧布局控件的高度设置 /
55 label->setMaximumHeight(this->height() / 5);
56 pushButton->setMaximumHeight(this->height() / 5);
57
58 / 按钮文件设置 /
59 pushButton->setText(“加 1”);
60
61 / 设置 widget 的布局为 vLayout /
62 widget->setLayout(vLayout);
63
64 / 将主窗体的布局设置为 hLayout /
65 mainWidget->setLayout(hLayout);
66
67 / 设置 mainWidget 为主窗体的居中 widget /
68 this->setCentralWidget(mainWidget);
69
70 / 信号槽连接,按钮点击,执行加一操作 /
71 connect(pushButton, SIGNAL(clicked()), this,
72 SLOT(pushButtonClieked()));
73
74 / 信号槽连接,历史记录项 index 发生变化,显示 count 大小 /
75 connect(undoStack, SIGNAL(indexChanged(int) ),
76 this, SLOT(showCountValue(int)));
77 }
78
79 / 入栈操作会自动调用 addCommand 的 redo /
80 void MainWindow::pushButtonClieked()
81 {
82 / 变量值加一 /
83 count++;
84
85 / value 指向 count 的地址 */
86 int value = &count;
87
88 / 用重写的 addCommand 类实例化 */
89 QUndoCommand add = new addCommand(value);
90
91 / 入栈 /
92 undoStack->push(add);
93 }
94
95 void MainWindow::showCountValue(int)
96 {
97 / 标签用于显示计算结果 */
98 label->setText(“计算结果:” + QString::number(count));
99 }
100
101 MainWindow::~MainWindow()
102 {
103
lue 指向 count 的地址 */
86 int value = &count;
87
88 / 用重写的 addCommand 类实例化 */
89 QUndoCommand add = new addCommand(value);
90
91 / 入栈 /
92 undoStack->push(add);
93 }
94
95 void MainWindow::showCountValue(int)
96 {
97 / 标签用于显示计算结果 */
98 label->setText(“计算结果:” + QString::number(count));
99 }
100
101 MainWindow::~MainWindow()
102 {
103
104 }
- 1 #include “mainwindow.h”
-
main.cpp
- 由新建项目时生成,无改动
运行效果
- 点击“加 1”按钮,计算结果将加 1,用方向键或者鼠标进行选择右边的历史记录面板将进行重做或者回撤操作,同时应用程序输出窗口打印出 debug 信息,计算结果也将回到该步时的计算结果
undefined
undefined
undefined
undefined
undefined