Qt 系列(五)——数据列表

前言

这篇主要来聊下qt中数据列表的使用,绑定等,当然也都是些比较基础的,不存在什么花里胡哨的东西。

数据列表

qt中有单列的QListViewQListWidget,有表格QTableViewQTableWidget,有树状菜单QTreeViewQTreeWidget,具体的区别就是,View基于Model(玩过MVC的应该清楚视图与模型的绑定),Widget直接基于Item,Widget集成View,内部已经实现了默认的Model,通过方法addItem直接可以添加数据,我们主要来看下View的使用,毕竟这种便于数据维护。

QListView

列表视图一般用在一些像切换界面,菜单选择等的单列式数据展示,对应的Model为QStringListModel,当然也可以用更高级的QStandardItemModel,先来看下简单的实现效果。

数据绑定
1
2
3
4
5
// .h
#include <QStringListModel>
...
private:
QStringListModel* m_listModel;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void TestWidget::init()
{
m_listModel = new QStringListModel();

setConnection();
bindList();
}

void TestWidget::bindList()
{
QStringList list;
list.append(QStringLiteral("龙门石窟"));
list.append(QStringLiteral("白马寺"));
list.append(QStringLiteral("关林庙"));
m_listModel->setStringList(list);

ui->listView->setModel(m_listModel);
// 设置间距
ui->listView->setSpacing(5);
// 默认选中
QModelIndex index = m_listModel->index(0);
ui->listView->setCurrentIndex(index);
}

事件绑定

常规的使用,这里只演示下双击事件,其他事件查看QListView的事件机制对应搞就行了,做双击的时候记得先禁用修改事件,默认是双击可以切换成LineEdit做修改。

1
2
// 禁用修改
ui->listView->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
1
2
3
4
5
6
7
8
9
10

void TestWidget::listViewDoubleClicked(const QModelIndex& index)
{
std::cout << "clicked index : " << index.row() << std::endl;
}

void TestWidget::setConnection()
{
connect(ui->listView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(listViewDoubleClicked(const QModelIndex&)));
}
右键菜单

通过以下方式打开ListView的右键菜单,然后再创建个菜单绑定到ListView中,当然同时也可以绑定QMenu对应Action的事件来做进一步的使用,这个后面用到再进行示例的演示。

1
2
// 右键菜单
ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

void TestWidget::init()
{
// ...
m_listMenu = new QMenu(ui->listView);
m_listMenu->addAction("test1");
m_listMenu->addAction("test2");
}

void TestWidget::listContextMenuShow(const QPoint& pos)
{
m_listMenu->exec(ui->listView->mapToGlobal(pos));
}

void TestWidget::setConnection()
{
connect(ui->listView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(listViewDoubleClicked(const QModelIndex&)));
// 绑定右键菜单
connect(ui->listView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(listContextMenuShow(const QPoint&)));
}

QListView

QTableView

表格视图在一些与数据打交道的应用上尤为常见,根据不同的数据做对应的列展示,数据绑定等比较方便,一般对应的Model为QStandardItemModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// .h
#include <QStandardItemModel>
#include <vector>

// 定义个数据集合结构体
struct TestItem
{
int id;
QString name;
int age;
short sex;
QString location;
};


private:
QStandardItemModel* m_tableModel;
std::vector<TestItem> m_data;
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
// .cpp
void TestWidget::bindTable()
{
QStringList header;
header << "id" << QStringLiteral("姓名") << QStringLiteral("性别") << QStringLiteral("年龄") << QStringLiteral("地址");
m_tableModel->setHorizontalHeaderLabels(header);

for (int i = 0; i < m_data.size(); i++)
{
m_tableModel->setItem(i, 0, new QStandardItem(QString::number(m_data[i].id)));
m_tableModel->setItem(i, 1, new QStandardItem(m_data[i].name));
m_tableModel->setItem(i, 2, new QStandardItem(m_data[i].sex == 1 ? QStringLiteral("男") : QStringLiteral("女")));
m_tableModel->setItem(i, 3, new QStandardItem(QString::number(m_data[i].age)));
m_tableModel->setItem(i, 4, new QStandardItem(m_data[i].location));

for (int j = 0; j < 5; j++)
{
m_tableModel->item(i, j)->setTextAlignment(Qt::AlignCenter);
}
}

ui->tableView->setModel(m_tableModel);

// 选中一整行
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
// 不显示网格
ui->tableView->setShowGrid(false);
// 双色显示
ui->tableView->setAlternatingRowColors(true);
// 隐藏垂直标题栏
ui->tableView->verticalHeader()->hide();
// 列宽自适应
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// 设置默认行高
ui->tableView->verticalHeader()->setDefaultSectionSize(40);
// 取消列编辑
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
}

void TestWidget::initData()
{
for (int i = 0; i < 10; i++)
{
TestItem item;
item.id = i + 1;
item.name = QString("test%1").arg(i + 1);
item.sex = i % 2 == 0 ? 1 : 2;
item.age = (i + 1) * 5;
item.location = QStringLiteral("大洛阳");
m_data.push_back(item);
}
}

至于事件、右键菜单同QListView,这里就不再多说了,看下效果。

QTableView

QTreeView

树状列表一般像组织架构、系统菜单、角色权限设置、目录结构等会比较常用,个人使用这个确实不多,大致看下用法吧。

1
2
// .h
QStandardItemModel* m_treeModel;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// .cpp
void TestWidget::bindTree()
{
for (int i = 0; i < 5; i++)
{
QStandardItem* item = new QStandardItem(QString("item %1").arg(i));

item->setCheckable(true);
if (i % 2 == 0)
{
for (int j = 0; j < 3; j++)
{
QStandardItem* childItem = new QStandardItem(QString("child item %1").arg(j));
childItem->setCheckable(true);
item->appendRow(childItem);
}
}
m_treeModel->setItem(i, item);
}
ui->treeView->setModel(m_treeModel);
ui->treeView->setHeaderHidden(true);
}

可以看到,实质上QStandardItem本身已经支持树型结构,通过appendRow来添加子节点。

其他的像点击啊右键菜单也是类似,至于选中态这种等后续鼓捣过实际用到再补充吧。

QTreeView

小结

数据展示目的就是为了查阅、维护、做数据分析,少不了后续涉及到增删改查,一个个来吧,鼓捣东西这条路走开了就停不下来了。


Qt 系列(五)——数据列表
http://www.aprilblank.top/qt/data_list.html
作者
AprilBlank
发布于
2022年6月27日
许可协议