C++ Qt 学习(九):模型视图代理
Robot_Yue
于 2023-11-16 21:44:27 发布
阅读量888
收藏 4
点赞数 2
分类专栏: C++ Qt 学习 文章标签: c++ qt 学习 MVD 模型 视图 代理
版权
C++ Qt 学习
专栏收录该内容
12 篇文章12 订阅
订阅专栏
1. Qt 模型视图代理
Qt 模型视图代理,也可以称为 MVD 模式
模型(model)、视图(view)、代理(delegate)
主要用来显示编辑数据
1.1 模型
模型 (Model) 是视图与原始数据之间的接口
原始数据可以是:数据库的一个数据表、内存中的一个 StringList,磁盘文件结构等
QAbstractItemModel 是所有模型的祖宗类,其它 model 类都派生于它
1.2 视图
视图 (View) 是显示和编辑数据的界面组件
主要的视图组件有 QListView、QTreeView 和 QTableView
QListWidget、QTreeWidget 和 QTableWidget 是视图类的简化版
它们不使用数据模型,而是将数据直接存储在组件的每个项里
QAbstractItemView 是所有视图的祖宗类,其它 view 类都派生于它
1.3 代理
代理 (Delegate) 为视图组件提供数据编辑器
如在表格组件中,编辑一个单元格的数据时,缺省是使用一个 QLineEdit 编辑框
代理负责从数据模型获取相应的数据,然后显示在编辑器里,修改数据后,又将其保存到数据模型中
2. QTableView 应用
tableView.pro
QT += core gui
// 使用 QAxObject 需添加下行
// The QAxObject class provides a QObject that wraps a COM object.
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets axcontainer
1
2
3
4
5
2.1 widget.ui
2.2 主窗口
2.2.1 widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include "cintspindelegate.h"
#include "cfloatspindelegate.h"
#include "ccomboboxdelegate.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_btnOpenExcel_clicked();
void on_btnReshowData_clicked();
void OnCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
void on_btnAppendLast_clicked();
void on_btnAppend_clicked();
void on_btnDeleteSelectedLine_clicked();
private:
Ui::Widget *ui;
QStandardItemModel *m_pItemModel; // 数据模型
QItemSelectionModel *m_pSelectionModel; // Item 选择模型
CIntSpinDelegate m_intSpinDelegate; // 整型数 spinbox 代理
CFloatSpinDelegate m_floatSpinDelegate; // 浮点数 spinbox 代理
CComboBoxDelegate m_comboBoxDelegate; // combobox 代理
};
#endif // WIDGET_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2.2.2 widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QAxObject>
#include <QFileDialog>
#include <QStandardPaths>
static const int COLUMN_COUNT = 7;
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
ui->setupUi(this);
showMaximized();
m_pItemModel = new QStandardItemModel(1, COLUMN_COUNT, this);
m_pSelectionModel = new QItemSelectionModel(m_pItemModel); // Item 选择模型
// 选择当前单元格变化时的信号与槽
connect(m_pSelectionModel, &QItemSelectionModel::currentChanged, this, &Widget::OnCurrentChanged);
ui->tableView->setModel(m_pItemModel); // 设置数据模型
ui->tableView->setSelectionModel(m_pSelectionModel); // 设置选择模型
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
// 给第 3,4,5 列设置自定义代理组件
ui->tableView->setItemDelegateForColumn(3, &m_floatSpinDelegate);
ui->tableView->setItemDelegateForColumn(4, &m_intSpinDelegate);
ui->tableView->setItemDelegateForColumn(5, &m_comboBoxDelegate);
}
Widget::~Widget() {
delete ui;
}
// 打开 excel
void Widget::on_btnOpenExcel_clicked() {
QAxObject *excel = new QAxObject(this);
excel->setControl("Excel.Application");
excel->setProperty("Visible", false); // 显示窗体看效果,选择 ture 将会看到 excel 表格被打开
excel->setProperty("DisplayAlerts", true);
QAxObject *workbooks = excel->querySubObject("WorkBooks"); // 获取工作簿(excel文件)集合
QString str = QFileDialog::getOpenFileName(this, u8"打开excel",
"D:/MyQtCreatorProject/9_2_tableView",
u8"Excel 文件(*.xls *.xlsx)");
// 打开刚才选定的 excel
workbooks->dynamicCall("Open(const QString&)", str);
QAxObject *workbook = excel->querySubObject("ActiveWorkBook");
QAxObject *worksheet = workbook->querySubObject("WorkSheets(int)",1);
QAxObject *usedRange = worksheet->querySubObject("UsedRange"); // 获取表格中的数据范围
QVariant var = usedRange->dynamicCall("Value"); // 将所有的数据读取到 QVariant 容器中保存
QList<QList<QVariant>> excel_list; // 用于将 QVariant 转换为 Qlist 的二维数组
QVariantList varRows = var.toList();
if (varRows.isEmpty()) {
return;
}
const int row_count = varRows.size();
QVariantList rowData;
for (int i = 0; i < row_count; ++i) {
rowData = varRows[i].toList();
excel_list.push_back(rowData);
}
// 将每一行的内容放到 contentList
QList<QStringList> contentList;
for (int i = 0; i < row_count; i++) {
QList<QVariant> curList = excel_list.at(i);
int curRowCount = curList.size();
QStringList oneLineStrlist;
for (int j = 0; j < curRowCount; j++) {
QString content = curList.at(j).toString();
oneLineStrlist << content;
}
contentList << oneLineStrlist;
}
workbook->dynamicCall("Close(Boolean)", false);
excel->dynamicCall("Quit(void)");
delete excel;
// 解析 contentList,填充 tableView
int rowCounts = contentList.size();
QStandardItem *aItem;
// 遍历行
for (int i = 0; i < rowCounts; i++) {
QStringList tmpList = contentList[i];
if(i == 0) {
// 设置表头
m_pItemModel->setHorizontalHeaderLabels(tmpList);
} else {
int j;
for (j = 0; j < COLUMN_COUNT - 1; j++) {
// 不包含最后一列
aItem = new QStandardItem(tmpList.at(j));
m_pItemModel->setItem(i-1, j, aItem); // 为模型的某个行列位置设置 Item
}
// 设置最后一列
aItem = new QStandardItem(contentList[0].at(j)); // 获取最后一列的指针
aItem->setCheckable(true); // 设置可以使用 check 控件
if (tmpList.at(j) == "0")
aItem->setCheckState(Qt::Unchecked); // 根据数据设置 check 状态
else
aItem->setCheckState(Qt::Checked);
m_pItemModel->setItem(i-1 , j, aItem); // 设置最后一列
}
}
}
// 选择单元格变化时的响应
void Widget::OnCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
Q_UNUSED(previous);
if (current.isValid()) { // 当前模型索引有效
ui->textEdit->clear();
ui->textEdit->append(QString::asprintf(u8"当前单元格:%d行,%d列",
current.row(),current.column())); // 显示模型索引的行和列号
QStandardItem *aItem;
aItem = m_pItemModel->itemFromIndex(current); // 从模型索引获得 item
ui->textEdit->append(u8"单元格内容:" + aItem->text()); // 显示 item 的文字内容
}
}
// 在表格最后一行添加
void Widget::on_btnAppendLast_clicked() {
QList<QStandardItem*> aItemList;
QStandardItem *aItem;
for (int i = 0; i < COLUMN_COUNT - 1; i++) { // 不包含最后 1 列
aItem = new QStandardItem(u8"自定义");
aItemList << aItem;
}
// 获取最后一列的表头文字
QString str = m_pItemModel->headerData(m_pItemModel->columnCount()-1, Qt::Horizontal, Qt::DisplayRole).toString();
aItem = new QStandardItem(str);
aItem->setCheckable(true);
aItemList<<aItem; // 添加到容器
m_pItemModel->insertRow(m_pItemModel->rowCount(), aItemList); // 插入一行,需要每个 Cell 的 Item
QModelIndex curIndex = m_pItemModel->index(m_pItemModel->rowCount()-1, 0); // 创建最后一行的 ModelIndex
// 如果之前点击了表格,清空选择项
m_pSelectionModel->clearSelection();
// 设置刚插入的行为当前选择行
m_pSelectionModel->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}
void Widget::on_btnAppend_clicked() {
QList<QStandardItem*> aItemList;
QStandardItem *aItem;
for(int i = 0; i < COLUMN_COUNT-1; i++) {
aItem = new QStandardItem(u8"自定义");
aItemList << aItem;
}
// 获取表头文字
QString str = m_pItemModel->headerData(m_pItemModel->columnCount()-1, Qt::Horizontal, Qt::DisplayRole).toString();
aItem = new QStandardItem(str);
aItem->setCheckable(true);
aItemList<<aItem;
QModelIndex curIndex = m_pSelectionModel->currentIndex(); // 获取当前选中项的模型索引
m_pItemModel->insertRow(curIndex.row(), aItemList); // 在当前行的前面插入一行
m_pSelectionModel->clearSelection(); // 清除已有选择
m_pSelectionModel->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}
// 删除选择的行
void Widget::on_btnDeleteSelectedLine_clicked() {
QModelIndex curIndex = m_pSelectionModel->currentIndex(); // 获取当前选择单元格的模型索引
if (curIndex.row() == m_pItemModel->rowCount() - 1) { // 如果是最后一行
m_pItemModel->removeRow(curIndex.row()); // 删除最后一行
} else {
m_pItemModel->removeRow(curIndex.row()); // 删除一行,并重新设置当前选择行
m_pSelectionModel->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}
}
// 将 tableView 的数据显示在 textEdit
void Widget::on_btnReshowData_clicked() {
ui->textEdit->clear(); // 清空
QStandardItem *aItem;
QString str;
// 获取表头文字
int i, j;
for (i = 0; i < m_pItemModel->columnCount(); i++) {
aItem = m_pItemModel->horizontalHeaderItem(i); // 获取表头的一个项数据
str = str + aItem->text() + "\t"; // 用 tab 间隔文字
}
ui->textEdit->append(str); // 添加为文本框的一行
//获取数据区的每行
for (i = 0; i < m_pItemModel->rowCount(); i++) {
str = "";
for (j = 0; j<m_pItemModel->columnCount()-1; j++) {
aItem = m_pItemModel->item(i,j);
str = str + aItem->text() + QString::asprintf("\t"); //以 tab 分隔
}
aItem = m_pItemModel->item(i, j); // 最后一行
if (aItem->checkState() == Qt::Checked)
str = str + "1";
else
str = str + "0";
ui->textEdit->append(str);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
2.3 整型数 spinbox 代理
2.3.1 cintspindelegate.h
#ifndef CINTSPINDELEGATE_H
#define CINTSPINDELEGATE_H
#include <QStyledItemDelegate>
class CIntSpinDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
CIntSpinDelegate(QObject *parent=0);
// 自定义代理组件必须继承以下 4 个函数
// 创建编辑组件
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
// 从数据模型获取数据,显示到代理组件中
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
// 将代理组件的数据,保存到数据模型中
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const Q_DECL_OVERRIDE;
// 更新代理编辑组件的大小
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
};
#endif // CINTSPINDELEGATE_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2.3.2 cintspindelegate.cpp
#include "cintspindelegate.h"
#include <QSpinBox>
CIntSpinDelegate::CIntSpinDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
QWidget *CIntSpinDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option, const QModelIndex &index) const {
// 创建代理编辑组件
Q_UNUSED(option);
Q_UNUSED(index);
QSpinBox *editor = new QSpinBox(parent); // 创建一个 QSpinBox
editor->setFrame(false); // 设置为无边框
editor->setMinimum(0);
editor->setMaximum(120);
return editor; // 返回此编辑器
}
void CIntSpinDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
// 从数据模型获取数据,显示到代理组件中
// 获取数据模型的模型索引指向的单元的数据
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox*>(editor); // 强制类型转换
spinBox->setValue(value); // 设置编辑器的数值
}
void CIntSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
// 将代理组件的数据,保存到数据模型中
QSpinBox *spinBox = static_cast<QSpinBox*>(editor); // 强制类型转换
spinBox->interpretText(); // 解释数据,如果数据被修改后,就触发信号
int value = spinBox->value(); // 获取 spinBox 的值
model->setData(index, value, Qt::EditRole); //更新到数据模型
}
void CIntSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
// 设置组件大小
Q_UNUSED(index);
editor->setGeometry(option.rect);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2.4 浮点数 spinbox 代理
2.4.1 cfloatspindelegate.h
#ifndef CFLOATSPINDELEGATE_H
#define CFLOATSPINDELEGATE_H
#include <QObject>
#include <QWidget>
#include <QStyledItemDelegate>
class CFloatSpinDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
CFloatSpinDelegate(QObject *parent=0);
// 自定义代理组件必须继承以下4个函数
// 创建编辑组件
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
};
#endif // CFLOATSPINDELEGATE_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2.4.2 cfloatspindelegate.cpp
#include "cfloatspindelegate.h"
#include <QDoubleSpinBox>
CFloatSpinDelegate::CFloatSpinDelegate(QObject *parent):QStyledItemDelegate(parent) {}
QWidget *CFloatSpinDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option, const QModelIndex &index) const {
Q_UNUSED(option);
Q_UNUSED(index);
QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setDecimals(2);
editor->setMaximum(100);
return editor;
}
void CFloatSpinDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
float value = index.model()->data(index, Qt::EditRole).toFloat();
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
spinBox->setValue(value);
}
void CFloatSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
spinBox->interpretText();
float value = spinBox->value();
QString str = QString::asprintf("%.2f", value);
model->setData(index, str, Qt::EditRole);
}
void CFloatSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
editor->setGeometry(option.rect);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2.5 combobox 代理
2.5.1 ccomboboxdelegate.h
#ifndef CCOMBOBOXDELEGATE_H
#define CCOMBOBOXDELEGATE_H
#include <QItemDelegate>
class CComboBoxDelegate : public QItemDelegate {
Q_OBJECT
public:
CComboBoxDelegate(QObject *parent=0);
// 自定义代理组件必须继承以下4个函数
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
};
#endif // CCOMBOBOXDELEGATE_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2.5.2 ccomboboxdelegate.cpp
#include "ccomboboxdelegate.h"
#include <QComboBox>
CComboBoxDelegate::CComboBoxDelegate(QObject *parent) : QItemDelegate(parent) {}
QWidget *CComboBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option, const QModelIndex &index) const {
QComboBox *editor = new QComboBox(parent);
editor->addItem(u8"优");
editor->addItem(u8"良");
editor->addItem(u8"一般");
return editor;
}
void CComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
QString str = index.model()->data(index, Qt::EditRole).toString();
QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->setCurrentText(str);
}
void CComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QString str = comboBox->currentText();
model->setData(index, str, Qt::EditRole);
}
void CComboBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const {
editor->setGeometry(option.rect);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
3. QListView 应用
3.1 widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QStringListModel>
#include <QMenu>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
void initMenu();
private slots:
void on_btnAddItem_clicked();
void on_btnDeleteItem_clicked();
void on_btnInsert_clicked();
void on_btnClearAllData_clicked();
void on_btnReshow_clicked();
void on_showRightMenu(const QPoint& pos);
void OnActionDelete();
// 链接 listview 的 clicked 信号
void on_listView_clicked(const QModelIndex &index);
private:
Ui::Widget *ui;
QStringListModel* m_pStringListModel;
QMenu *m_pMenu;
};
#endif // WIDGET_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
3.2 widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMenu>
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
ui->setupUi(this);
this->setWindowTitle(u8"QListView使用教程");
QStringList strList;
strList << u8"北京" << u8"上海" << u8"深圳" << u8"广东"
<< u8"南京" << u8"苏州" << u8"西安";
// 创建数据模型
m_pStringListModel = new QStringListModel(this);
// 为模型设置 StringList,会导入 StringList 的内容
m_pStringListModel->setStringList(strList);
// 为 listView 设置数据模型
ui->listView->setModel(m_pStringListModel);
// 设置 listview 编辑属性
// 双击与选择
//ui->listView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
initMenu();
// listview 右键菜单
ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->listView, &QListView::customContextMenuRequested, this, &Widget::on_showRightMenu);
}
Widget::~Widget() {
delete ui;
}
// 添加 item
void Widget::on_btnAddItem_clicked() {
// 在尾部插入一空行, 不添加就把最后一行给替换了
m_pStringListModel->insertRow(m_pStringListModel->rowCount());
// 获取最后一行
QModelIndex index = m_pStringListModel->index(m_pStringListModel->rowCount() - 1, 0);
m_pStringListModel->setData(index,"new item", Qt::DisplayRole); // 设置显示文字
// 设置新添加的行选中
ui->listView->setCurrentIndex(index);
}
// 删除选中的项
void Widget::on_btnDeleteItem_clicked() {
// 获取当前选中的 modelIndex
QModelIndex index = ui->listView->currentIndex();
// 删除当前行
m_pStringListModel->removeRow(index.row());
}
// 插入一项
void Widget::on_btnInsert_clicked() {
// 获取选中 model Index
QModelIndex index=ui->listView->currentIndex();
// 在当前行的前面插入一行
m_pStringListModel->insertRow(index.row());
m_pStringListModel->setData(index, "inserted item", Qt::DisplayRole);
ui->listView->setCurrentIndex(index);
}
// 回显 listview数据
void Widget::on_btnReshow_clicked() {
// 获取数据模型的 StringList
QStringList tmpList = m_pStringListModel->stringList();
ui->textEdit->clear(); // 文本框清空
for (int i = 0; i < tmpList.count(); i++) {
// 显示数据模型的 StringList()返回的内容
ui->textEdit->append(tmpList.at(i));
}
}
// 清除所有数据
void Widget::on_btnClearAllData_clicked() {
m_pStringListModel->removeRows(0, m_pStringListModel->rowCount());
}
void Widget::initMenu() {
m_pMenu = new QMenu(ui->listView);
QAction *pAc1 = new QAction(u8"删除", ui->listView);
QAction *pAc2 = new QAction(u8"插入", ui->listView);
QAction *pAc3 = new QAction(u8"置顶", ui->listView);
QAction *pAc4 = new QAction(u8"排到最后", ui->listView);
m_pMenu->addAction(pAc1);
m_pMenu->addAction(pAc2);
m_pMenu->addAction(pAc3);
m_pMenu->addAction(pAc4);
// 注意在 exec 前链接信号槽,因为 exec 会阻塞主线程,
// 如果 connect 写在 exec 代码之后,信号槽将无法链接
connect(pAc1, &QAction::triggered, this, &Widget::OnActionDelete);
}
void Widget::on_showRightMenu(const QPoint& pos) {
if (!((ui->listView->selectionModel()->selectedIndexes()).empty())) {
m_pMenu->exec(QCursor::pos()); // 在当前鼠标位置显示
}
}
void Widget::OnActionDelete() {
// 获取当前 modelIndex
QModelIndex index = ui->listView->currentIndex();
// 删除当前行
m_pStringListModel->removeRow(index.row());
}
void Widget::on_listView_clicked(const QModelIndex &index) {
ui->textEdit->clear(); // 文本框清空
// 显示 QModelIndex 的行、列号
ui->textEdit->append(QString::asprintf(u8"当前项:row=%d, column=%d",
index.row(), index.column()));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
Robot_Yue
关注
2
4
0
专栏目录
一篇文章带你看懂Qt MVC(模型、视图、代理)编程———附带详细图文和实...
7-10
MV编程就是model(模型)、view(视图)、control(Delegate(代理))编程,就是把模型和视图分开来。1. 1 视图视图:例如QTableView、QListView、QTreeView,就是总体数据的呈现方式。 例如效果如下图。1. 2 代理代理:把视图里改变的值反馈到模型里;把模型里的数据库呈现到视图里。 例如:如下图里的商品名称和单位就...
Qt开发 | Qt模型视图代理(Model-View-Delegate)
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_42994487/article/details/134451496