Qt之界面数据存储与获取(使用setUserData()和userData())
在GUI开发中,往往需要在界面中存储一些有用的数据,这些数据可以来配置文件、注册表、数据库、或者是server。
无论来自哪里,这些数据对于用户来说都是至关重要的,它们在交互过程中大部分都会被用到,例如:单击一个用户头像,显示该用户的详细信息(等级、昵称、姓名、个人说明)。
常见接口
Qt中,可以通过绝大部分已有的接口来存数数据、获取数据。例如:
存储数据
- setData()
- setItemData()
- setUserData()
获取数据:
- data()
- itemData()
- userData()
常用的基本就这些,当然,还有其他的一些接口。。。
数据源
为了便于演示,我们定义两个数据源:结构体User、枚举LANGUAGE。
// 用户信息
struct User : QObjectUserData {
int nID; // ID
QString strName; // 用户名
};
// 语言
typedef enum{
UI_ZH, // 中文
UI_EN // 英文
} LANGUAGE;
Q_DECLARE_METATYPE(User)
Q_DECLARE_METATYPE(LANGUAGE)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
其中,User定义为QObjectUserData类型,为了后面setUserData()和userData()使用。如果不使用这两个接口,则不需要定义为QObjectUserData。
绝大部分存储用户数据的接口都使用的是QVariant,也就是我们常说的“万能变量”。对于自定义数据类型,如果要使用QVariant,就必须使用Q_DECLARE_METATYPE注册。
setData()和data()
创建一个QListWidget列表,添加5个Item项,然后给每一个都存储属于自己的数据。
单独存储
通过setData(),我们可以单独存储用户数据,使用Qt::UserRole、Qt::UserRole + 1……
QListWidget *pListWidget = new QListWidget(this);
int i = 0;
do {
++i;
QListWidgetItem *pItem = new QListWidgetItem(pListWidget);
pItem->setData(Qt::UserRole, i); // 用户数据
pItem->setData(Qt::UserRole + 1, QString("Qter %1").arg(i)); // 用户数据
pItem->setText(QString("Item %1").arg(i)); // 文本
pListWidget->addItem(pItem);
} while (i < 5);
// 连接信号槽
connect(pListWidget, &QListWidget::itemClicked, this, &MainWindow::onItemClicked);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
槽函数,获取用户数据,执行相应操作。
void onItemClicked(QListWidgetItem *item) {
int nID = item->data(Qt::UserRole).toInt(); // 获取用户数据
QString strName = item->data(Qt::UserRole + 1).toString(); // 获取用户数据
qDebug() << "ID : " << nID;
qDebug() << "Name : " << strName;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
整体存储
也可以通过setData()进行整体存储,这时候只需要使用Qt::UserRole即可,把用户数据当成一个结构体来存储。
QListWidget *pListWidget = new QListWidget(this);
int i = 0;
do {
++i;
QListWidgetItem *pItem = new QListWidgetItem(pListWidget);
User user;
user.nID = i;
user.strName = QString("Qter %1").arg(i);
pItem->setData(Qt::UserRole, QVariant::fromValue(user)); // 设置用户数据
pItem->setText(QString("Item %1").arg(i));
pListWidget->addItem(pItem);
} while (i < 5);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
槽函数,获取用户数据,执行相应操作。
void onItemClicked(QListWidgetItem *item) {
QVariant variant = item->data(Qt::UserRole); // 获取用户数据
User user = variant.value<User>();
qDebug() << "ID : " << user.nID;
qDebug() << "Name : " << user.strName;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
无论那种方式都可以,如果在信号和槽的传递过程中,参数过多,建议使用“整体存储”方式。
setItemData()和itemData()
在Qt之国际化一节中,分享了多语言的切换,下面就以此为例:
QComboBox *pComboBox = new QComboBox(this);
pComboBox->addItem("Chinese");
pComboBox->addItem("English");
pComboBox->setItemData(0, QVariant::fromValue(UI_ZH)); // 设置用户数据
pComboBox->setItemData(1, QVariant::fromValue(UI_EN)); // 设置用户数据
// 连接信号槽
connect(pComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &MainWindow::onCurrentIndexChanged);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
槽函数,获取用户数据,执行相应操作。
void onCurrentIndexChanged(int index) {
// 获取发送者
QObject *pObject = this->sender();
QComboBox *pComboBox = qobject_cast<QComboBox *>(pObject);
// 获取用户数据
QVariant variant = pComboBox->itemData(index);
LANGUAGE language = variant.value<LANGUAGE>();
qDebug() << "Language : " << language;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
setUserData()和userData()
通过setUserData(),我们可以存储用户数据。
注意:用户数据需要被定义为QObjectUserData类型。
QPushButton *pButton = new QPushButton(this);
pButton->setText("Qter");
// 用户数据
User *pUser = new User();
pUser->nID = 1;
pUser->strName = "Qter";
pButton->setUserData(Qt::UserRole, pUser); // 设置用户数据
// 连接信号槽
connect(pButton, &QPushButton::clicked, this, &MainWindow::onClicked);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
槽函数,获取用户数据,执行相应操作。
void onClicked() {
// 获取发送者
QObject *pObject = this->sender();
QPushButton *pButton = qobject_cast<QPushButton *>(pObject);
// 获取用户数据
User *pUser = (User *)(pButton->userData(Qt::UserRole));
qDebug() << "ID : " << pUser->nID;
qDebug() << "Name : " << pUser->strName;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
通过userData()可以获取QObjectUserData数据,然后转换成我们需要的类型User。
自定义数据
用现有的接口固然方便,有时对于复杂的功能,我们也不得不自定义。
举一个简单的例子:
#include <QPushButton>
class PushButton : public QPushButton
{
Q_OBJECT
public:
explicit PushButton(QWidget *parent = 0)
: QPushButton (parent),
m_nID(-1),
m_strName("")
{
}
void setID(int id) {
m_nID = id;
}
void setName(QString name) {
m_strName = name;
}
int id() const {
return m_nID;
}
QString name() const {
return m_strName;
}
private:
int m_nID;
QString m_strName;
};
- 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
- 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
我们定义了一个按钮QPushButton,可以通过setID()、setName()来设置ID和名称信息,如果要获取信息,则可以调用id()、name()函数。
使用很简单:
PushButton *pButton = new PushButton(this);
pButton->setText("Qter");
// 设置自定义数据
pButton->setID(1);
pButton->setName("Qter");
// 连接信号槽
connect(pButton, &QPushButton::clicked, this, &MainWindow::onClicked);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
槽函数,获取用户数据,执行相应操作。
void onClicked() {
// 获取发送者
QObject *pObject = this->sender();
PushButton *pButton = qobject_cast<PushButton *>(pObject);
// 获取用户数据
qDebug() << "ID : " << pButton->id();
qDebug() << "Name : " << pButton->name();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
基本的数据存储与获取方式就这些,以后会经常用到,Good luck。
http://blog.csdn.net/u011012932/article/details/52413012
Qt之界面数据存储与获取(使用setUserData()和userData())的更多相关文章
- Qt之界面数据存储与获取(userData)
http://blog.csdn.net/u011012932/article/details/52413012#comments
- 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...
- JAVA之旅(十七)——StringBuffer的概述,存储,删除,获取,修改,反转,将缓存区的数据存储到数组中,StringBuilder
JAVA之旅(十七)--StringBuffer的概述,存储,删除,获取,修改,反转,将缓存区的数据存储到数组中,StringBuilder 讲完String,我们来聊聊他的小兄弟 一.StringB ...
- 看懂Qt源代码-Qt源码的对象数据存储
第一次看Qt源代码的人都会被其代码所迷惑,经常会看到代码中的d_ptr成员.d_func(函数)和Q_DECLARE_PRIVATE等奇怪的宏,总是让人一头雾水,下面这篇文章转自http://www. ...
- 在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据
在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据.如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zook ...
- go-redis 基于beego正确使用序列化存储数据和反序列化获取数据
安装go-redis // 安装命令 go get github.com/gomodule/redigo/redis // 导入使用 import( "github.com/gomodule ...
- 我的Vue之旅 09 数据数据库表的存储与获取实现 Mysql + Golang
第四期 · 将部分数据存储至Mysql,使用axios通过golang搭建的http服务器获取数据. 新建数据库 DROP DATABASE VUE; create database if not e ...
- MySQL存储和获取数据
---恢复内容开始--- 一.MySQL存储引擎? 1.引擎定义 存储引擎其实就是如何存取数据,如何为存储的数据建立索引和如何更新.查询数据等技术的实现方法.因为在关系型数据苦中数据是以表格的形式,所 ...
- Android中数据存储(一)
国庆没有给国家添堵,没有勾搭妹子,乖乖的写着自己的博客..... 本文将为大家介绍Android中数据存储的五种方式,数据存储可是非常重要的知识哦. 一,文件存储数据 ①在ROM存储数据 关于在ROM ...
随机推荐
- Polyline转Polygon
IGeometry geo = feature.ShapeCopy; IGeometryCollection pPolyline = geo as IGeometryCollection; ISegm ...
- CAF(C++ actor framework)(序列化之复杂类,分析 还有自己不懂的细思恐极函数实现)(三)
这里应该是序列化的最后一篇.感觉自己写的不是很好,也一点点在学习.这次就不贴上代码了.代码在github上的announce5.cpp.代码简单,但是分析下去会有细思恐极的感觉! 先看一下几个函数是干 ...
- 在20上链接db2
首先 db2 connect to CICMDB user ptqs using ptqs; db2进入,出现db2 prep cperftest_bysqlc.sqC bindfile; 就可以sq ...
- C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化
本文是基本上一篇博文进行改进而成,上一篇请见: C++对象的JSON序列化与反序列化探索 此处就不多说了,直接上代码. 1. 序列化基类 #pragma once #include <strin ...
- JS焦点图,JS 多个页面放多个焦点图
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- WinForm窗体间如何传值的几种方法
(转) 窗体间传递数据,无论是父窗体操作子窗体,还是子窗体操作符窗体,有以下几种方式: 公共静态变量: 使用共有属性: 使用委托与事件: 通过构造函数把主窗体传递到从窗体中: 一.通过静态变量 特点: ...
- Winform DataGridView添加列头checkbox
using System; using System.Data; using System.Drawing; using System.Windows.Forms; using Yanwen.Logi ...
- mac 上的版本控制工具SmartSVN9.0.4(破解版)
附带上破解版安装说明: 1.在MAC上选中SmartSVN.dmg,右键->打开2.双击syntevo_keygen.jar 如果没有安装java会自动提示安装的3.输入Name Email(随 ...
- HTML5如何重塑O2O用户体验
低频次垂直O2O服务应该继续开发原生APP吗?大家有没有发现做一个APP的推广成本和获取用户的成本越来越高?第二,用户安装APP之后,用户并不是经常点击使用APP的,那这是为什么?数据表明90%的O2 ...
- delphi 仅带下划线的TEdit控件
在做录入框的时候,很希望有一个只带下划线的文本框,网上介绍的很多,有自己做组件的,须不知Delphi下只需要简单设置几个属性即可达到目的.