背景:本地用数据库管理用户数据不方便,需要手动增删查改账户,存在安全风险,两个方案可供替代:1.调用接口来获取用户信息json,通过软件解析json字符串提取用户账号信息。2.直接跳过调用接口那一步,选择xml文件路径并解析。(由于第一种方案行不通,故使用第二种)
步骤一:界面设计
添加一个选择文件框,选择文件时将文件路径保存进编辑框里面,下次界面显示直接加载该路径文件并将文件数据显示在列表视图里面
步骤二:
导入所需的类
-
#include <QTimer>
-
#include <QByteArray>
-
#include <QXmlStreamReader>
-
#include <QSortFilterProxyModel>
-
#include <QTableView>
-
#include <QStandardItemModel>
-
#include <QStyledItemDelegate>
-
#include <QPainter>
-
#include <QHeaderView>
-
#include <QFileDialog>
在构造函数里设置列表视图的列信息,其中用户卡号通过代理设置为*隐藏,并对用户工号进行升序排序,
-
this->m_userModel = new QStandardItemModel;
-
->setModel(m_userModel);
-
this->m_userModel->setHorizontalHeaderItem(0, new QStandardItem(tr("CardID")));
-
this->m_userModel->setHorizontalHeaderItem(1, new QStandardItem(tr("WorkID")));
-
this->m_userModel->setHorizontalHeaderItem(2, new QStandardItem(tr("Level")));
-
->verticalHeader()->setVisible(false);;
-
->horizontalHeader()->setStyleSheet("QHeaderView::section {"
-
"color: black;border: 1px solid #6c6c6c;}");
-
->setEditTriggers(QAbstractItemView::NoEditTriggers);
-
->setSelectionBehavior(QAbstractItemView::SelectRows);
-
// 设置代理到CardID列
-
PasswordDelegate *delegate = new PasswordDelegate();
-
->setItemDelegateForColumn(0, delegate);
-
-
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
-
proxyModel->setSourceModel(this->m_userModel);
-
-
proxyModel->setSortRole(Qt::EditRole);
-
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
-
proxyModel->sort(1, Qt::AscendingOrder);
-
-
->setModel(proxyModel);
步骤三:编写加载XML函数
打开文件:
- 首先创建一个
QFile
对象,使用传入的filePath
作为文件路径。 - 然后尝试以只读和文本模式打开文件。如果打开失败,函数会输出错误信息并返回,终止后续操作。
-
QFile file(filePath);
-
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-
qDebug() << "Cannot open file for reading:" << file.errorString();
-
return;
-
}
创建 XML 读取器:
- 使用
QXmlStreamReader
来解析打开的 XML 文件。这个类提供了一种简单的方式来逐步读取 XML 数据。
QXmlStreamReader xml(&file);
解析 XML 数据:
- 通过一个循环,函数不断读取 XML 数据,直到到达文件末尾或遇到错误。
-
()
方法会返回当前读取的 token 类型。-
while (!xml.atEnd() && !xml.hasError()) {
-
QXmlStreamReader::TokenType token = xml.readNext();
-
处理开始元素:
- 当读取到一个开始元素时,检查该元素的名称是否为
RegularItemNode
。如果是,则准备提取该节点的属性。 - 定义了三个字符串变量
cardCodeID
、cardCode
和cardCodeLevelA
,用于存储从 XML 中提取的值。 - 创建一个
QList<QStandardItem*>
来存储将要添加到模型中的项。
-
if (token == QXmlStreamReader::StartElement) {
-
if (xml.name() == "RegularItemNode") {
-
QString cardCodeID;
-
QString cardCode;
-
QString cardCodeLevelA;
-
QList<QStandardItem*> items;
提取属性:
- 通过循环遍历当前元素的所有属性,检查属性名称并提取相应的值。
- 对于
CardCodeID
和CardCode
,使用base64StrToString
函数将其值从 Base64 编码转换为字符串,并将其添加到items
列表中。 - 对于
CardCodeLevelA
,直接将其值添加到items
列表中。
-
for (const QXmlStreamAttribute &attr : xml.attributes()) {
-
if (attr.name() == "CardCodeID") {
-
cardCodeID = base64StrToString(attr.value().toString());
-
items << new QStandardItem(cardCodeID);
-
}
-
else if (attr.name() == "CardCode") {
-
cardCode = base64StrToString(attr.value().toString());
-
items << new QStandardItem(cardCode);
-
}
-
else if (attr.name() == "CardCodeLevelA") {
-
cardCodeLevelA = attr.value().toString();
-
items << new QStandardItem(cardCodeLevelA);
-
}
-
}
将数据添加到模型:
- 将提取到的项(
items
列表)添加到m_userModel
中,这通常是一个QStandardItemModel
的实例,用于在用户界面中显示数据。
this->m_userModel->appendRow(items);
处理 XML 错误:
- 在循环结束后,检查是否在解析过程中遇到错误。如果有错误,输出错误信息。
-
if (xml.hasError()) {
-
qDebug() << "XML error:" << xml.errorString();
-
}
-
关闭文件:
file.close();
最后,显示效果如下:
代理类相关代码:
-
class PasswordDelegate : public QStyledItemDelegate {
-
public:
-
PasswordDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
-
-
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
-
// 获取原始数据
-
QString text = index.data().toString();
-
-
// 使用星号替代实际内容
-
QString maskedText((), '*');
-
-
// 绘制文本
-
painter->save();
-
painter->drawText(, Qt::AlignLeft | Qt::AlignVCenter, maskedText);
-
painter->restore();
-
}
-
};