是这样的,个人在Qt中时常因为item的赋值问题而苦恼,所以就写了这篇文章来作为一个备份,如果外来者观看的话建议通过目录索引到关键内容以提高查阅效率
案例1 文章列表的展现以及点击后的详细页面
前提
首先,你需要一个在文章类中写一个注册宏
像这样:
Q_DECLARE_METATYPE(article)
Q_DECLARE_METATYPE(article*)
然后这是文章类的头文件:
#ifndef ARTICLE_H
#define ARTICLE_H
#include <QString>
#include <vector>
#include <QMetaType>
class article
{
public:
article(const QString &title = "", const QString &tags = "", const QString &author = "", const QString &content = "", bool isban = false, int likes = 0)
: title(title), tags(tags), author(author), content(content), isban(isban), likes(likes) {}
//读取,不做出改变
QString get_articleTitle() const;
QString get_articleTag() const;
QString get_articleAuthor() const;
QString get_articleContent() const;
bool get_articleIsban() const;
int get_articleLikes() const;
//设置,做出改变
void set_articleTitle(QString title);
void set_articleTag(QString tags);
void set_articleAuthor(QString author);
void set_articleContent(QString ci);
void set_articleIsban(bool isBan);
void set_articleLikes(int likes);
private:
QString title;
QString tags;
QString author;
QString content;
bool isban;
int likes;
};
// 在全局范围内注册自定义类型
Q_DECLARE_METATYPE(article)
Q_DECLARE_METATYPE(article*)
#endif // ARTICLE_H
之后,要写一个QList<article>的列表来存储文章列表
个人倾向于认为查看文章列表是用户的一个行为,所以我把这个列表写在了用户类(知道这样写效率低,但是这只是个样例)
#ifndef USER_H
#define USER_H
#include "article.h"
#include <QString>
#include <QList>
class User
{
public:
enum role { banUser, user, admin };
QList<article> searchArticleList; //文章类的列表
QList<article> OriginalArticleList;
User(QString &username, QString &password, role initialRole = user)
: username(username), password(password), userRole(initialRole) { loadArticlesFromFile();}
// 获取用户名
QString get_username() const { return username; }
// 获取密码
QString get_password() const { return password; }
// 获取用户角色
role get_userRole() const { return userRole; }
// 设置用户名
void set_username(const QString &newUsername) { username = newUsername; }
// 设置密码
void set_password(const QString &newPassword) { password = newPassword; }
// 设置用户角色
void set_userRole(role newRole) { userRole = newRole; }
//写文章
void writeArticle(const QString &title,const QString &tags,const QString &author,const QString &content);
//阅读文章
void readArticle(const QString &title);
//点赞文章
void likeArticle(const QString &title);
//从文档加载文章
void loadArticlesFromFile();
//三个排序
void sortArticlesByTitle();
void sortArticlesByLikes();
void sortArticlesByAuthor();
private:
QString username;
QString password;
role userRole;
};
#endif // USER_H
然后,就是要从文档中读取文章,然后将文章存储到文章列表中了(就是searchArticleList和OriginalArticleList)
void User::loadArticlesFromFile() {
// 清空现有文章列表
OriginalArticleList.clear();
QFile file("articles.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "无法打开文件!";
return;
}
QTextStream in(&file);
QString line;
// 遍历文件并加载所有文章
while (!in.atEnd()) {
line = in.readLine();
// 假设每行的文章数据格式为: 标题|标签|内容
QStringList parts = line.split("###"); // 使用 "###" 作为分隔符
if (parts.size() == 6) {
QString articleTitle = parts[0];
QString articleTags = parts[1];
QString articleAuthor = parts[2];
QString articleContent = parts[3];
bool articleIsBanned = parts[4].toInt() == 1;
int articleLikes = parts[5].toInt();
// 创建 article 对象
article loadedArticle(articleTitle, articleTags, articleAuthor, articleContent, articleIsBanned, articleLikes);
// 添加到文章列表
OriginalArticleList.append(loadedArticle);
searchArticleList.append(loadedArticle);
}
}
file.close();
}
正文
之后,就是最关键的部分:如何将article类的list赋值到item上
首先你要申明一个QListWidget:
QListWidget *articleList = new QListWidget(this);
然后写一个for遍历前提的文章列表,在遍历中将文章列表赋值到item中,最后将item加入到上面申明的articlelist上
for (const article& art : currentUser.searchArticleList) {
QString title = art.get_articleTitle();
QString tags = art.get_articleTag();
QString textInItem = title + "\n" + tags;
// 创建一个新的 QListWidgetItem 并将文本添加到该项
QListWidgetItem *item = new QListWidgetItem(textInItem);
// 将文章对象存储在列表项的 UserRole 数据中
item->setData(Qt::UserRole, QVariant::fromValue(art));
// 将新创建的项添加到 QListWidget
articleList->addItem(item);
}
对上述代码做出以下阐述:
setData() | 设置item的数据 |
Qt::UserRole | 用户自定义的数据类型 |
QVariant | QVariant具有自动类型转换的功能,可以在需要时将存储的数据自动转换为目标类型 |
QVariant::fromValue() | 对于自定义类型,要使QVariant::fromValue 能够工作,该类型需要被Qt的元对象系统所识别。这通常意味着该类型需要继承自QObject(如果它是一个类)并使用Q_OBJECT宏,同时可能还需要为该类型注册一个元类型(使用qRegisterMetaType 函数或Q_DECLARE_METATYPE 宏)(个人选择Q_DECLARE_METATYPE ) |

实现效果:
后文
如何点击显示详细内容?
个人选择是点击就切成显示详细信息的页面
切换页面:
private slots :
void articleClicked(QListWidgetItem *item);
connect(articleList,&QListWidget::itemClicked,this,&guidingPage::articleClicked);
void guidingPage::articleClicked(QListWidgetItem *item) {
if (item == nullptr) {
qDebug() << "Item is null, skipping the click event!";
return; // 退出函数,避免崩溃
}
article selectedArticle = item->data(Qt::UserRole).value<article>();
ArticleDetailPage *detailPage = new ArticleDetailPage(currentUser, selectedArticle);
detailPage->show();
this->close();
传值到另一个界面后如何显示:
ArticleDetailPage::ArticleDetailPage(User user, const article &art, QWidget *parent)
: currentUser(user), QWidget(parent), articleDetail(art)
{
// 创建标题标签
QLabel *titleLabel = new QLabel(art.get_articleTitle(), this);
titleLabel->setStyleSheet("font-size: 40px; font-weight: bold; color: #333;");
// 创建作者标签
QLabel *authorLabel = new QLabel("作者: " + art.get_articleAuthor(), this);
authorLabel->setStyleSheet("font-size: 20px; color: #555;");
}
实现效果:

就写这么多吧
然后个人其实还是有些关于QWidgetListItem的一些小问题的,比如如何让item自己刷新,而不用跟随页面刷新而刷新,这个问题个人作为qt方面完全自学的新手还在学习中.当然,因为学校数据结构大作业的原因,qt程序需要打包上交给学校方面,但是个人对于的打包总是打包的一塌糊涂,要么就是少了拓展,要么打开就闪退(在别人电脑上会闪退,但是自己电脑运行打包好的程序是没问题的)😭
然后个人用Enigma Virtual Box封包了闪退版后甚至直接变成了这样:

关于这个版本问题,我同学给出的解答是:用汇编修复导入表........
罢了,今日起,猛学汇编!