Qt之界面数据存储与获取(使用setUserData()和userData())

本文介绍Qt中使用setData、setItemData及setUserData等方法存储和获取界面数据的方式,并给出具体示例,包括整体存储和单独存储两种场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。

<think>我们正在讨论如何在Qt的QPushButton中设置自定义数据。根据引用内容,有两种主要方法: 1. 使用属性(property)机制:通过设置动态属性来存储自定义数据。 2. 在自定义按钮类中添加成员变量:通过继承QPushButton并添加额外的数据成员。 根据用户的问题,他想要设置自定义数据,我们可以分别介绍这两种方法。 方法一:使用属性(property) Qt提供了动态属性的机制,允许我们在运行时为QObject派生对象(包括QPushButton)添加属性。 步骤: a. 使用`setProperty`方法设置属性。 b. 使用`property`方法获取属性值。 示例代码(C++): QPushButton *button = new QPushButton("Click me"); // 设置一个名为"customData"的属性,值为一个整数(或字符串等其他类型) button->setProperty("customData", 42); // 整数 button->setProperty("customDataString", "my data"); // 字符串 获取属性: int data = button->property("customData").toInt(); QString dataStr = button->property("customDataString").toString(); 注意:属性名可以自定义,但需要确保在获取使用相同的名字。另外,属性值可以是QVariant类型支持的各种类型。 方法二:继承QPushButton并添加成员变量 如果我们希望有更强的类型检查更多的操作,可以创建自定义按钮类。 步骤: a. 创建一个继承自QPushButton的类。 b. 添加需要的成员变量访问方法(getter/setter)。 示例(C++头文件): class MyButton : public QPushButton { Q_OBJECT public: explicit MyButton(QWidget *parent = nullptr); void setCustomData(int data) { m_customData = data; } int customData() const { return m_customData; } private: int m_customData; }; 然后在代码中使用MyButton代替QPushButton,并直接使用setCustomDatacustomData方法。 根据引用[2]中的示例,我们可以看到如何使用属性在槽函数中获取自定义数据: QPushButton *btn = qobject_cast<QPushButton*>(sender()); if (btn) { // 获取之前设置的属性 QString testData = btn->property("TestData").toString(); // 使用testData } 因此,如果用户只是临时需要附加一些数据,使用属性机制更为方便。如果需要一个具有特定行为数据的按钮,则推荐使用继承的方式。 用户问题:如何在QPushButton中设置自定义数据? 我们提供了两种方法,并给出了示例。 现在,根据系统级指令,我们需要生成相关问题。</think>在 Qt 中为 `QPushButton` 设置自定义数据有两种常用方法,以下是具体实现: ### 方法 1:使用动态属性(推荐) 通过 `setProperty()` 设置自定义数据,用 `property()` 读取数据: ```cpp // 设置自定义数据(支持任意QVariant类型) QPushButton *button = new QPushButton("按钮"); button->setProperty("userID", 1001); // 整数 button->setProperty("userName", "张三"); // 字符串 button->setProperty("isAdmin", true); // 布尔值 // 在槽函数中获取数据 void onButtonClicked() { QPushButton *btn = qobject_cast<QPushButton*>(sender()); if(btn) { int id = btn->property("userID").toInt(); QString name = btn->property("userName").toString(); bool admin = btn->property("isAdmin").toBool(); // 使用数据... } } ``` > 优势:无需创建子类,动态添加任意类型数据[^2] ### 方法 2:继承自定义按钮类 创建派生类添加数据成员: ```cpp // 头文件 class CustomButton : public QPushButton { Q_OBJECT public: explicit CustomButton(QWidget *parent = nullptr); void setUserData(const UserData &data); // 自定义数据结构 UserData userData() const; private: UserData m_customData; // 自定义数据成员 }; // 实现文件 void CustomButton::setUserData(const UserData &data) { m_customData = data; // 可触发界面更新 update(); } // 使用示例 CustomButton *btn = new CustomButton(this); btn->setUserData({1001, "张三", true}); ``` ### 两种方法对比 | **特性** | 动态属性法 | 继承子类法 | |------------------|------------------------------|------------------------------| | 实现复杂度 | ⭐⭐ 简单(无需子类) | ⭐⭐⭐ 需创建子类 | | 数据类型支持 | ⭐⭐ 任意QVariant类型 | ⭐⭐⭐ 任意自定义类型 | | 数据持久性 | ⭐⭐ 随对象存在 | ⭐⭐⭐ 强类型成员变量 | | 适用场景 | 临时数据/简单标记 | 复杂数据/需封装逻辑的场景 | > 提示:动态属性法在Python中同样有效,语法为 `btn.setProperty("key", value)`[^3]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值