OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2479|回复: 0

《I.MX6U 嵌入式Qt开发指南》第七章 Qt控件 7.8 项目视图组(基于模型)

[复制链接]

1070

主题

1081

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4443
金钱
4443
注册时间
2019-5-8
在线时间
1199 小时
发表于 2022-7-29 14:49:04 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2022-7-29 15:05 编辑

1)实验平台:正点原子阿尔法Linux开发板
2)  章节摘自【正点原子】《I.MX6U 嵌入式Qt开发指南》

3)购买链接:https://detail.tmall.com/item.htm?id=609033604451
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/arm-linux/zdyz-i.mx6ull.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子阿尔法Linux交流群:1027879335




第七章 Qt控件


7.8 项目视图组(基于模型)
image002.jpg

       上图需要注意的是,在低版本的Qt,Column View与Undo View是没有封装成可视控件形式在Qt Creator中。
以上各个控件的解释如下:
(1)           List View:清单视图
(2)           Tree View:树形视图
(3)           Table View:表视图
(4)           Column View:列表视图
(5)           Undo View:撤销列表视图
以下是各个控件的简介:
QListWidget继承QListView。QListWidget类提供了一个基于项的列表小部件。QListWidget是一个便捷的类,它提供了一个类似于QListView(下一小节将讲到)提供的列表视图,但是提供了一个用于添加和删除项目的基于项目的经典接口。QListWidget使用内部模型来管理列表中的每个QListWidgetItem。QListView是基于model的,需要自己来建模(例如建立QStringListModel、QSqlTableModel等),保存数据,这样就大大降低了数据冗余,提高了程序的效率,但是需要我们对数据建模有一定了解,初学者可以去了解Qt中的数据模型,方便导入数据,管理数据。而QListWidget是一个升级版本的QListView,它已经自己为我们建立了一个数据存储模型(QListWidgetItem),操作方便,直接调用addItem即可添加项目(ICON,文字)。
QTreeWidget继承QTreeView。QTreeWidget类提供了一个使用预定义树模型的树视图。
QTreeWidget类是一个便捷的类,它提供了一个标准的树小部件,具有一个类似于qt3中的QListView类所使用的基于项目的经典接口。该类基于Qt的模型/视图体系结构,并使用默认模型来保存项,每个项都是QTreeWidgetItem。
QTableWidget继承QTableView。QTableWidget类提供了一个带有默认模型的基于项的表视图。表小部件为应用程序提供标准的表显示工具。QTableWidget中的项由QTableWidgetItem提供。
QColumnView继承QAbstractItemView。QColumnView在许多QListViews中显示一个模型,每个QListViews对应树中的每个层次结构。这有时被称为级联列表。QColumnView类是模型/视图类之一,是Qt模型/视图框架的一部分。QColumnView实现了由QAbstractItemView类定义的接口,以允许它显示由派生自QAbstractItemModel类的模型提供的数据。
QUndoView继承QlistView。QUndoView类显示QUndoStack的内容。QUndoView是一个QListView,它显示在撤销堆栈上推送的命令列表。总是选择最近执行的命令。选择不同的命令会导致调用QUndoStack::setIndex(),将文档的状态向后或向前滚动到新命令。可以使用setStack()显式地设置堆栈。或者,可以使用setGroup()来设置QUndoGroup对象。当组的活动堆栈发生变化时,视图将自动更新自身。

7.8.1 QListView7.8.1.1 控件简介
QListView继承QAbstractItemView,被QListWidget 和QUndoView继承。QListView类提供模型上的列表或图标视图。QListView以简单的非分层列表或图标集合的形式显示存储在模型中的项。该类用于提供以前由QListBox和QIconView类提供的列表和图标视图,但是使用了Qt的模型/视图体系结构提供的更灵活的方法。QListView是基于Model,而QListWidget是基于Item,这是它们的本质区别。QListView需要建模,所以减少了冗余的数据,程序效率高;而QListWidget是一个升级版本的QListView(实质是封装好了model的QListView),它已经自己为我们建立了一个数据存储模型(QListWidgetItem),操作方便,直接调用addItem即可添加项目(ICON,文字)。
QT提供了一些现成的models用于处理数据项(这些是Qt处理数据模型的精华,如果用到Qt数据模型,下面这些是经常要用到的):
(1)           QStringListModel 用于存储简单的QString列表。
(2)           QStandardItemModel 管理复杂的树型结构数据项,每项都可以包含任意数据。
(3)           QDirModel  提供本地文件系统中的文件与目录信息。
(4)           QSqlQueryModel, QSqlTableModel,QSqlRelationTableModel用来访问数据库。


7.8.1.2 用法示例
例40_qlistview,清单图(难度:简单)。使用一个ListView控件,展示如何在列表中插入数据,其中表中的内容可编辑,可删除。
在新建例程中不要勾选“Generate form”,默认继承QMainWindow类即可。项目新建完成,如下图。
image004.jpg
   在头文件“mainwindow.h”具体代码如下。
  1. mainwindow.h编程后的代码
  2. 1   #ifndef MAINWINDOW_H
  3. 2   #define MAINWINDOW_H
  4. 3
  5. 4   #include <QMainWindow>
  6. 5   #include <QListView>
  7. 6   #include <QStringListModel>
  8. 7
  9. 8   class MainWindow : public QMainWindow
  10. 9   {
  11. 10      Q_OBJECT
  12. 11
  13. 12  public:
  14. 13      MainWindow(QWidget *parent = nullptr);
  15. 14      ~MainWindow();
  16. 15
  17. 16  private:
  18. 17      /* QListView对象 */
  19. 18      QListView *listView;
  20. 19      /* 字符串模型对象 */
  21. 20      QStringListModel *stringListModel;
  22. 21
  23. 22  };
  24. 23  #endif // MAINWINDOW_H
复制代码
在源文件“mainwindow.cpp”具体代码如下。
  1. mainwindow.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   MainWindow::MainWindow(QWidget *parent)
  5. 4       : QMainWindow(parent)
  6. 5   {
  7. 6       /* 设置主窗口位置与大小 */
  8. 7       this->setGeometry(0, 0, 800, 480);
  9. 8
  10. 9       /* 实例化 */
  11. 10      listView = new QListView(this);
  12. 11      /* 将listView居中 */
  13. 12      setCentralWidget(listView);
  14. 13
  15. 14      QStringList strList;
  16. 15      strList<<"高三(1)班"<<"高三(2)班"<<"高三(3)班";
  17. 16
  18. 17      /* 实例化,字符串模型 */
  19. 18      stringListModel = new QStringListModel(strList);
  20. 19
  21. 20      /* 向表中插入一段数据 */
  22. 21      listView->setModel(stringListModel);
  23. 22      /* 设置为视图为图标模式 */
  24. 23      listView->setViewMode(QListView::IconMode);
  25. 24      /* 设置为不可拖动 */
  26. 25      listView->setDragEnabled(false);
  27. 26  }
  28. 27
  29. 28  MainWindow::~MainWindow()
  30. 29  {
  31. 30  }
复制代码
在源文件“main.cpp”具体代码如下。由新建项目时生成,无改动。
  1. main.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   #include <QApplication>
  5. 4
  6. 5   int main(int argc, char *argv[])
  7. 6   {
  8. 7       QApplication a(argc, argv);
  9. 8       MainWindow w;
  10. 9       w.show();
  11. 10      return a.exec();
  12. 11  }
复制代码
7.8.1.3 运行效果
程序编译运行的结果如下。双击表格中的项,可修改表格的内容,同时也可以删除内容等。
image006.jpg

7.8.2 QTreeView
7.8.2.1 控件简介
QTreeView继承QAbstractItemView,被QTreeWidget继承。QTreeView类提供树视图的默认模型/视图实现。QTreeView实现了模型项的树表示。该类用于提供以前由QListView类提供的标准分层列表,但是使用了Qt的模型/视图体系结构提供的更灵活的方法。

7.8.2.2 用法示例
例41_qtreeview,仿word标题(难度:简单)。要使一个QTreeView能够显示数据,需要构造一个model并设置QTreeView。Qt提供了一些类型的Model,其中最常用的就是这个QStandardItemModel类,一般可以满足大部分需求。另外,表头的内容也由这个model管理,setHorizontalHeaderLabels函数可以设置共有多少列、每列文字。一级标题直接使用 appendRow方法添加到model上,次级标题则是添加到第一个父级标题上,依次构成父子关系树。
在新建例程中不要勾选“Generate form”,默认继承QMainWindow类即可。项目新建完成,如下图。
image008.jpg
   在头文件“mainwindow.h”具体代码如下。
  1. mainwindow.h编程后的代码
  2. 1   #ifndef MAINWINDOW_H
  3. 2   #define MAINWINDOW_H
  4. 3
  5. 4   #include <QMainWindow>
  6. 5   #include <QTreeView>
  7. 6
  8. 7   class MainWindow : public QMainWindow
  9. 8   {
  10. 9       Q_OBJECT
  11. 10
  12. 11  public:
  13. 12      MainWindow(QWidget *parent = nullptr);
  14. 13      ~MainWindow();
  15. 14
  16. 15  private:
  17. 16      QTreeView  *treeView;
  18. 17
  19. 18  };
  20. 19  #endif // MAINWINDOW_H
复制代码
在源文件“mainwindow.cpp”具体代码如下。
  1. mainwindow.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   #include <QStandardItemModel>
  5. 4   #include <QStandardItem>
  6. 5
  7. 6   MainWindow::MainWindow(QWidget *parent)
  8. 7       : QMainWindow(parent)
  9. 8   {
  10. 9       /* 设置窗口的位置与大小 */
  11. 10      this->setGeometry(0, 0, 800, 480);
  12. 11      /* 实例化QTreeView对象 */
  13. 12      treeView = new QTreeView(this);
  14. 13      /* 居中 */
  15. 14      setCentralWidget(treeView);
  16. 15
  17. 16      /* 构建Model */
  18. 17      QStandardItemModel *sdiModel = new QStandardItemModel(treeView);
  19. 18      sdiModel->setHorizontalHeaderLabels(
  20. 19                  QStringList()<<QStringLiteral("标题")
  21. 20                  << QStringLiteral("名称")
  22. 21                  );
  23. 22
  24. 23      for(int i = 0; i < 5; i++) {
  25. 24          /* 一级标题 */
  26. 25          QList<QStandardItem*> items1;
  27. 26          QStandardItem* item1 =
  28. 27                  new QStandardItem(QString::number(i));
  29. 28          QStandardItem* item2 =
  30. 29                  new QStandardItem(QStringLiteral("一级标题"));
  31. 30          /* 添加项一 */
  32. 31          items1.append(item1);
  33. 32          /* 添加项二 */
  34. 33          items1.append(item2);
  35. 34          /* appendRow方法添加到model上 */
  36. 35          sdiModel->appendRow(items1);
  37. 36
  38. 37          for(int j = 0; j < 5; j++) {
  39. 38              /* 在一级标题后面插入二级标题 */
  40. 39              QList<QStandardItem*> items2;
  41. 40              QStandardItem* item3 =
  42. 41                      new QStandardItem(QString::number(j));
  43. 42              QStandardItem* item4 =
  44. 43                      new QStandardItem(QStringLiteral("二级标题"));
  45. 44              items2.append(item3);
  46. 45              items2.append(item4);
  47. 46              /* 使用appendRow方法添加到item1上 */
  48. 47              item1->appendRow(items2);
  49. 48          }
  50. 49      }
  51. 50      /* 设置Model给treeView */
  52. 51      treeView->setModel(sdiModel);
  53. 52  }
  54. 53
  55. 54  MainWindow::~MainWindow()
  56. 55  {
  57. 56  }
复制代码
在源文件“main.cpp”具体代码如下。由新建项目时生成,无改动。
  1. main.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   #include <QApplication>
  5. 4
  6. 5   int main(int argc, char *argv[])
  7. 6   {
  8. 7       QApplication a(argc, argv);
  9. 8       MainWindow w;
  10. 9       w.show();
  11. 10      return a.exec();
  12. 11  }
复制代码
7.8.2.3 运行效果
程序编译运行的结果如下。可以点击数字来展开二级标题。
image010.jpg

7.8.3 QTableView
7.8.3.1 控件简介
QTableView继承QAbstractItemView,被QTableWidget继承。QTableView类提供了表视图的默认模型/视图实现。QTableView实现了一个表视图,用于显示来自模型的项。该类用于提供以前由QTable类提供的标准表,但使用Qt的模型/视图体系结构提供的更灵活的方法。

7.8.3.2 用法示例
例42_qtableview,表格视图(难度:简单)。要使一个QTableView能够显示数据,需要构造一个model并设置给QTableView。Qt提供了一些类型的Model,其中最常用的就是这个QStandardItemModel类,一般可以满足大部分需求。另外,表头的内容也由这个model管理,setHorizontalHeaderLabels函数可以设置共有多少列、每列文字。
在新建例程中不要勾选“Generate form”,默认继承QMainWindow类即可。项目新建完成,如下图。
image012.jpg
   在头文件“mainwindow.h”具体代码如下。
  1. mainwindow.h编程后的代码
  2. 1   #ifndef MAINWINDOW_H
  3. 2   #define MAINWINDOW_H
  4. 3
  5. 4   #include <QMainWindow>
  6. 5   #include <QTableView>
  7. 6
  8. 7   class MainWindow : public QMainWindow
  9. 8   {
  10. 9       Q_OBJECT
  11. 10
  12. 11  public:
  13. 12      MainWindow(QWidget *parent = nullptr);
  14. 13      ~MainWindow();
  15. 14
  16. 15  private:
  17. 16      QTableView *tableView;
  18. 17  };
  19. 18  #endif // MAINWINDOW_H
复制代码
在源文件“mainwindow.cpp”具体代码如下。
  1. mainwindow.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2   #include <QStandardItemModel>
  4. 3   #include <QHeaderView>
  5. 4
  6. 5   MainWindow::MainWindow(QWidget *parent)
  7. 6       : QMainWindow(parent)
  8. 7   {
  9. 8       /* 设置窗口的位置与大小 */
  10. 9       this->setGeometry(0, 0, 800, 480);
  11. 10      tableView = new QTableView(this);
  12. 11      setCentralWidget(tableView);
  13. 12      /* 显示网格线 */
  14. 13      tableView->setShowGrid(true);
  15. 14
  16. 15      QStandardItemModel* model = new QStandardItemModel();
  17. 16      QStringList labels =
  18. 17              QObject::tr("语文,数学,英语").simplified().split(",");
  19. 18      /* 设置水平头标签 */
  20. 19      model->setHorizontalHeaderLabels(labels);
  21. 20
  22. 21      /* item */
  23. 22      QStandardItem* item = 0;
  24. 23      /* model插入项内容 */
  25. 24      for(int i = 0; i < 5; i++){
  26. 25          item = new QStandardItem("80");
  27. 26          model->setItem(i, 0, item);
  28. 27          item = new QStandardItem("99");
  29. 28          model->setItem(i, 1, item);
  30. 29          item = new QStandardItem("100");
  31. 30          model->setItem(i, 2, item);
  32. 31      }
  33. 32      /* 将model设置给tableView */
  34. 33      tableView->setModel(model);
  35. 34      /* 平均分列 */
  36. 35      tableView->horizontalHeader()
  37. 36              ->setSectionResizeMode(QHeaderView::Stretch);
  38. 37      /* 平均分行 */
  39. 38      tableView->verticalHeader()
  40. 39              ->setSectionResizeMode(QHeaderView::Stretch);
  41. 40  }
  42. 41
  43. 42  MainWindow::~MainWindow()
  44. 43  {
  45. 44  }
复制代码
在源文件“main.cpp”具体代码如下。由新建项目时生成,无改动。
  1. main.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   #include <QApplication>
  5. 4
  6. 5   int main(int argc, char *argv[])
  7. 6   {
  8. 7       QApplication a(argc, argv);
  9. 8       MainWindow w;
  10. 9       w.show();
  11. 10      return a.exec();
  12. 11  }
复制代码
7.8.3.3 运行效果
程序编译运行的结果如下。建立了一个成绩表格。
image014.jpg

7.8.4 QColumnView
7.8.4.1 控件简介
QColumnView继承QAbstractItemView。QColumnView在许多QListViews中显示一个模型,每个QListViews对应树中的每个层次结构。这有时被称为级联列表。QColumnView类是模型/视图类之一,是Qt模型/视图框架的一部分。QColumnView实现了由QAbstractItemView类定义的接口,以允许它显示由派生自QAbstractItemModel类的模型提供的数据。
7.8.4.2 用法示例
例43_qcolumnview,收货地址(难度:简单)。使用一个QColumnView,向其插入多级QStandardItem。这样就可以模拟成一个多级联的视图。与我们在像某宝,某东里填写的收货地址十分类似。
在新建例程中不要勾选“Generate form”,默认继承QMainWindow类即可。项目新建完成,如下图。
image016.jpg
在头文件“mainwindow.h”具体代码如下。

  1. mainwindow.h编程后的代码
  2. 1   #ifndef MAINWINDOW_H
  3. 2   #define MAINWINDOW_H
  4. 3
  5. 4   #include <QMainWindow>
  6. 5   #include <QColumnView>
  7. 6
  8. 7   class MainWindow : public QMainWindow
  9. 8   {
  10. 9       Q_OBJECT
  11. 10
  12. 11  public:
  13. 12      MainWindow(QWidget *parent = nullptr);
  14. 13      ~MainWindow();
  15. 14
  16. 15  private:
  17. 16      QColumnView *columnView;
  18. 17  };
  19. 18  #endif // MAINWINDOW_H
复制代码
在源文件“mainwindow.cpp”具体代码如下。
  1. mainwindow.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2   #include <QStandardItem>
  4. 3
  5. 4   MainWindow::MainWindow(QWidget *parent)
  6. 5       : QMainWindow(parent)
  7. 6   {
  8. 7       /* 设置主窗体显示位置与大小 */
  9. 8       this->setGeometry(0, 0, 800, 480);
  10. 9       QStandardItemModel *model = new QStandardItemModel;
  11. 10
  12. 11      /* 省份 */
  13. 12      QStandardItem *province = new QStandardItem("广东省");
  14. 13
  15. 14      /* 城市 */
  16. 15      QStandardItem *city1 = new QStandardItem("茂名市");
  17. 16      QStandardItem *city2 = new QStandardItem("中山市");
  18. 17
  19. 18      /* 添加城市到省份下 */
  20. 19      province->appendRow(city1);
  21. 20      province->appendRow(city2);
  22. 21
  23. 22      QStandardItem *town1 = new QStandardItem("电白镇");
  24. 23      QStandardItem *town2 = new QStandardItem("南头镇");
  25. 24
  26. 25      /* 添加城镇到城市下 */
  27. 26      city1->appendRow(town1);
  28. 27      city2->appendRow(town2);
  29. 28
  30. 29      QColumnView *columnView = new QColumnView;
  31. 30
  32. 31      /* 建立model */
  33. 32      model->appendRow(province);
  34. 33
  35. 34      /* 设置model */
  36. 35      columnView->setModel(model);
  37. 36
  38. 37      /* 设置居中 */
  39. 38      setCentralWidget(columnView);
  40. 39  }
  41. 40
  42. 41  MainWindow::~MainWindow()
  43. 42  {
  44. 43  }
复制代码
在源文件“main.cpp”具体代码如下。由新建项目时生成,无改动。
  1. main.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   #include <QApplication>
  5. 4
  6. 5   int main(int argc, char *argv[])
  7. 6   {
  8. 7       QApplication a(argc, argv);
  9. 8       MainWindow w;
  10. 9       w.show();
  11. 10      return a.exec();
  12. 11  }
复制代码
7.8.4.3 运行效果
程序编译运行的结果如下。当点击省份出现城市,点击城市出现城镇。
image018.jpg

7.8.5 QUndoView
7.8.5.1 控件简介
QUndoView继承QlistView。QUndoView类显示QUndoStack的内容。QUndoView是一个QListView,它显示在撤销堆栈上推送的命令列表。总是选择最近执行的命令。选择不同的命令会导致调用QUndoStack::setIndex(),将文档的状态向后或向前滚动到新命令。可以使用setStack()显式地设置堆栈。或者,可以使用setGroup()来设置QUndoGroup对象。当组的活动堆栈发生变化时,视图将自动更新自身。

7.8.5.2 用法示例
例44_qundoview,仿PS历史记录(难度:一般)。如果大家学习过PS,都知道PS里有个历史记录面板,点击就会撤回到历史记录的步骤。例子其实也可以参考Qt官方提供的例子“Undo Framework Example”。但是官方的例子过于复杂,整个理解下来需要花费大量时间。于是编者写一个仿PS历史记录的例子来加深大家对QUndoView的理解。
在新建例程中不要勾选“Generate form”,默认继承QMainWindow类即可。同时添加了两个新建文件》点击新建,选择C++》C++ Source File命名command.h和command.cpp文件,用于重写QUndoCommand。项目新建完成,如下图。
image020.jpg
在头文件“command.h”具体代码如下。
  1. command.h编程后的代码
  2. 1   #ifndef COMMAND_H
  3. 2   #define COMMAND_H
  4. 3
  5. 4   #include <QUndoCommand>
  6. 5   #include <QObject>
  7. 6
  8. 7   class addCommand : public QUndoCommand
  9. 8   {
  10. 9   public:
  11. 10      addCommand(int *value, QUndoCommand* parent = 0);
  12. 11      ~addCommand();
  13. 12
  14. 13      /* 重写重做与撤回方法 */
  15. 14      void redo() override;
  16. 15      void undo() override;
  17. 16
  18. 17  private:
  19. 18      /* 新的count */
  20. 19      int *new_count;
  21. 20
  22. 21      /* 旧的count */
  23. 22      int old_count;
  24. 23  };
  25. 24
  26. 25  #endif // COMMAND_H
复制代码
       在头文件“mainwindow.h”具体代码如下。
  1. mainwindow.h编程后的代码
  2. 1   #ifndef MAINWINDOW_H
  3. 2   #define MAINWINDOW_H
  4. 3
  5. 4   #include <QMainWindow>
  6. 5   #include <QUndoView>
  7. 6   #include <QUndoStack>
  8. 7   #include <QHBoxLayout>
  9. 8   #include <QVBoxLayout>
  10. 9   #include <QPushButton>
  11. 10  #include <QLabel>
  12. 11  #include <command.h>
  13. 12
  14. 13  class MainWindow : public QMainWindow
  15. 14  {
  16. 15      Q_OBJECT
  17. 16
  18. 17  public:
  19. 18      MainWindow(QWidget *parent = nullptr);
  20. 19      ~MainWindow();
  21. 20
  22. 21  private:
  23. 22      /* 水平布局 */
  24. 23      QHBoxLayout *hLayout;
  25. 24      /* 水平布局 */
  26. 25      QVBoxLayout *vLayout;
  27. 26      /* 用于容纳hLayout布局 */
  28. 27      QWidget *mainWidget;
  29. 28      /* 容器作用QWidget,用于容纳标签与按钮 */
  30. 29      QWidget *widget;
  31. 30      /* 存放 QUndoCommand命令的栈 */
  32. 31      QUndoStack *undoStack;
  33. 32      /* 历史记录面板 */
  34. 33      QUndoView *undoView;
  35. 34      /* 用于显示计算结果 */
  36. 35      QLabel *label;
  37. 36      /* 按钮 */
  38. 37      QPushButton *pushButton;
  39. 38      /* 计算结果 */
  40. 39      int count;
  41. 40
  42. 41  private slots:
  43. 42      void pushButtonClieked();
  44. 43      void showCountValue(int);
  45. 44  };
  46. 45  #endif // MAINWINDOW_H
复制代码
在源文件“command.cpp”具体代码如下。
  1. command.cpp编程后的代码
  2. 1   #include "command.h"
  3. 2   #include <QDebug>
  4. 3
  5. 4   addCommand::addCommand(int *value, QUndoCommand *parent)
  6. 5   {
  7. 6       /* 使用Q_UNUSED,避免未使用的数据类型 */
  8. 7       Q_UNUSED(parent);
  9. 8
  10. 9       /* undoView显示的操作信息 */
  11. 10      setText("进行了加1操作");
  12. 11
  13. 12      /* value的地址赋值给new_count */
  14. 13      new_count = value;
  15. 14
  16. 15      /* 让构造函数传过来的*new_count的值赋值给old_count */
  17. 16      old_count = *new_count;
  18. 17  }
  19. 18
  20. 19  /* 执行stack push时或者重做操作时会自动调用 */
  21. 20  void addCommand::redo()
  22. 21  {
  23. 22      /* 重新赋值给new_count */
  24. 23      *new_count = old_count;
  25. 24
  26. 25      /* 打印出*new_count的值 */
  27. 26      qDebug()<<"redo:"<<*new_count<<endl;
  28. 27  }
  29. 28
  30. 29  /* 回撤操作时执行 */
  31. 30  void addCommand::undo()
  32. 31  {
  33. 32      /* 回撤操作每次应减一 */
  34. 33      (*new_count)--;
  35. 34
  36. 35      /* 打印出*new_count的值 */
  37. 36      qDebug()<<"undo:"<<*new_count<<endl;
  38. 37  }
  39. 38
  40. 39  addCommand::~addCommand()
  41. 40  {
  42. 41
  43. 42  }
复制代码
在源文件“mainwindow.cpp”具体代码如下。
  1. mainwindow.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2   #include <QDebug>
  4. 3
  5. 4   MainWindow::MainWindow(QWidget *parent)
  6. 5       : QMainWindow(parent)
  7. 6   {
  8. 7       /* 设置主窗体显示的位置与大小 */
  9. 8       this->setGeometry(0, 0, 800, 480);
  10. 9
  11. 10      /* 实例一个水平布局,用于左侧按钮区域与右侧历史记录面板 */
  12. 11      hLayout = new QHBoxLayout();
  13. 12
  14. 13      /* 实例一个水平布局,用于左侧标签与按钮 */
  15. 14      vLayout = new QVBoxLayout();
  16. 15
  17. 16      /* 主Widget, 因为MainWindow自带一个布局,
  18. 17       * 我们要新建一个Widget容纳新布局
  19. 18       */
  20. 19      mainWidget = new QWidget();
  21. 20
  22. 21      /* 用于存放命令行栈 */
  23. 22      undoStack = new QUndoStack(this);
  24. 23
  25. 24      /* 用于容纳左侧标签与按钮布局 */
  26. 25      widget = new QWidget();
  27. 26
  28. 27      /* 历史记录面板实例化 */
  29. 28      undoView = new QUndoView(undoStack);
  30. 29
  31. 30      /* 实例一个按钮,用于加一操作 */
  32. 31      pushButton = new QPushButton();
  33. 32
  34. 33      /* 标签,用于显示计算结果 */
  35. 34      label = new QLabel();
  36. 35
  37. 36      /* 设置widget的大小 */
  38. 37      widget->setMinimumSize(400, 480);
  39. 38
  40. 39      /* 将两个widget添加到水平布局 */
  41. 40      hLayout->addWidget(widget);
  42. 41      hLayout->addWidget(undoView);
  43. 42
  44. 43      /* 初始化count的值 */
  45. 44      count = 0;
  46. 45
  47. 46      /* 显示初始化计算结果 */
  48. 47      label->setText("计算结果:" + QString::number(count));
  49. 48      label->setAlignment(Qt::AlignCenter);
  50. 49
  51. 50      /* 左侧布局 */
  52. 51      vLayout->addWidget(label);
  53. 52      vLayout->addWidget(pushButton);
  54. 53
  55. 54      /* 左侧布局控件的高度设置 */
  56. 55      label->setMaximumHeight(this->height() / 5);
  57. 56      pushButton->setMaximumHeight(this->height() / 5);
  58. 57
  59. 58      /* 按钮文件设置 */
  60. 59      pushButton->setText("加1");
  61. 60
  62. 61      /* 设置widget的布局为vLayout */
  63. 62      widget->setLayout(vLayout);
  64. 63
  65. 64      /* 将主窗体的布局设置为hLayout */
  66. 65      mainWidget->setLayout(hLayout);
  67. 66
  68. 67      /* 设置mainWidget为主窗体的居中widget */
  69. 68      this->setCentralWidget(mainWidget);
  70. 69
  71. 70      /* 信号槽连接,按钮点击,执行加一操作 */
  72. 71      connect(pushButton, SIGNAL(clicked()), this,
  73. 72              SLOT(pushButtonClieked()));
  74. 73
  75. 74      /* 信号槽连接,历史记录项index发生变化,显示count大小 */
  76. 75      connect(undoStack, SIGNAL(indexChanged(int) ),
  77. 76              this, SLOT(showCountValue(int)));
  78. 77  }
  79. 78
  80. 79  /* 入栈操作会自动调用addCommand的redo */
  81. 80  void MainWindow::pushButtonClieked()
  82. 81  {
  83. 82      /* 变量值加一 */
  84. 83      count++;
  85. 84
  86. 85      /* value指向count的地址 */
  87. 86      int *value = &count;
  88. 87
  89. 88      /* 用重写的addCommand类实例化 */
  90. 89      QUndoCommand *add = new addCommand(value);
  91. 90
  92. 91      /* 入栈 */
  93. 92      undoStack->push(add);
  94. 93  }
  95. 94
  96. 95  void MainWindow::showCountValue(int)
  97. 96  {
  98. 97      /* 标签用于显示计算结果 */
  99. 98      label->setText("计算结果:" + QString::number(count));
  100. 99  }
  101. 100
  102. 101 MainWindow::~MainWindow()
  103. 102 {
  104. 103
  105. 104 }
复制代码
在源文件“main.cpp”具体代码如下。由新建项目时生成,无改动。
  1. main.cpp编程后的代码
  2. 1   #include "mainwindow.h"
  3. 2
  4. 3   #include <QApplication>
  5. 4
  6. 5   int main(int argc, char *argv[])
  7. 6   {
  8. 7       QApplication a(argc, argv);
  9. 8       MainWindow w;
  10. 9       w.show();
  11. 10      return a.exec();
  12. 11  }
复制代码
7.8.5.3 运行效果
程序编译运行的结果如下。点击“加1”按钮,计算结果将加1,用方向键或者鼠标进行选择右边的历史记录面板将进行重做或者回撤操作,同时应用程序输出窗口打印出debug信息,计算结果也将回到该步时的计算结果。
本例总结:使用数学运算加一的方法,简单的说明了QUndoView的使用。如果大家想到有好QUndoView的使用情景就可以模仿本例再深度优化或者进行知识拓展。
image022.jpg




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-8 20:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表