我正在Qt中研究模型视图编程。我正在尝试使用自定义委托来实现自定义列表模型。这是一个简单的列表小部件,每行中都有一个带有一些标签的小部件。
窗口小部件什么也不显示。调试时,我注意到从不调用委托方法,因此我当然缺少了一些东西,但我不知道它是什么。
userinfo.h
#ifndef USERINFO_H
#define USERINFO_H
#include <QString>
#include <QTime>
#include <QImage>
class UserInfo
{
public:
UserInfo();
UserInfo(const UserInfo&);
~UserInfo();
QString getTitle() const;
QString getSubtitle() const;
QTime getTime() const;
QImage getAvatar() const;
void setTitle(const QString& value);
void setSubtitle(const QString& value);
void setTime(const QTime& value);
void setAvatar(const QImage& value);
private:
UserInfo(const QString& title);
UserInfo(const QString& title, const QString& subtitle, const QTime& time, const QImage& icon);
QString title;
QString subtitle;
QTime time;
QImage avatar;
};
Q_DECLARE_METATYPE(UserInfo)
#endif // USERINFO_H
userinfo.cpp
#include "userinfo.h"
static const int _regUserInfo = qRegisterMetaType<UserInfo>("UserInfo");
UserInfo::UserInfo()
: UserInfo("User")
{
}
UserInfo::UserInfo(const QString& title)
: UserInfo(title, "Comment", QTime(0,0,0,0), QImage(":/resources/icon.png"))
{
}
UserInfo::UserInfo(const QString& title, const QString& subtitle, const QTime& time, const QImage& icon) :
title(title),
subtitle(subtitle),
time(time),
avatar(icon)
{
}
QImage UserInfo::getAvatar() const
{
return avatar;
}
void UserInfo::setAvatar(const QImage& value)
{
avatar = value;
}
QTime UserInfo::getTime() const
{
return time;
}
void UserInfo::setTime(const QTime& value)
{
time = value;
}
QString UserInfo::getSubtitle() const
{
return subtitle;
}
void UserInfo::setSubtitle(const QString& value)
{
subtitle = value;
}
QString UserInfo::getTitle() const
{
return title;
}
void UserInfo::setTitle(const QString& value)
{
title = value;
}
UserInfo::UserInfo(const UserInfo&) = default;
UserInfo::~UserInfo() = default;
userlistmodel.h
#ifndef USERMODEL_H
#define USERMODEL_H
#include <QAbstractListModel>
#include "userinfo.h"
class UserListModel : public QAbstractListModel
{
public:
UserListModel(QObject* parent = nullptr);
int rowCount(const QModelIndex& parent) const;
QVariant data(const QModelIndex& index, int role) const;
bool setData(const QModelIndex& index, const QVariant& value, int role);
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
bool insertRows(int position, int row, const QModelIndex& parent=QModelIndex());
private:
QList<UserInfo> users;
};
#endif // USERMODEL_H
userlistmodel.cpp
#include "userlistmodel.h"
#include <QDebug>
UserListModel::UserListModel(QObject* parent) : QAbstractListModel(parent)
{
}
int UserListModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent)
return users.size();
}
QVariant UserListModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
if (index.row() >= users.size())
return QVariant();
return QVariant::fromValue<UserInfo>(users.at(index.row()));
}
bool UserListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
qDebug() << index.isValid();
qDebug() << (role == Qt::EditRole) ;
qDebug() <<value.canConvert<UserInfo>();
if (index.isValid() && role == Qt::EditRole && value.canConvert<UserInfo>()) {
users.replace(index.row(), value.value<UserInfo>());
emit dataChanged(index, index);
return true;
}
return false;
}
QVariant UserListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return QString("Column %1").arg(section);
else
return QString("Row %1").arg(section);
}
bool UserListModel::insertRows(int position, int rows, const QModelIndex &parent)
{
beginInsertRows(QModelIndex(), position, position+rows-1);
for (int row = 0; row < rows; ++row) {
users.insert(position, UserInfo());
}
endInsertRows();
return true;
}
userentrywidget.h
#ifndef USERENTRYWIDGET_H
#define USERENTRYWIDGET_H
#include <QWidget>
#include <QLabel>
#include "userinfo.h"
class UserEntryWidget : public QWidget
{
Q_OBJECT
public:
explicit UserEntryWidget(QWidget* parent = nullptr);
void setUserInfo(const UserInfo& user);
private:
QLabel *avatar, *title, *subtitle, *time;
};
#endif // USERENTRYWIDGET_H
userentrywidget.cpp
#include "userentrywidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
UserEntryWidget::UserEntryWidget(QWidget* parent) : QWidget(parent)
{
avatar = new QLabel();
title = new QLabel("title");
subtitle = new QLabel("subtitle");
time = new QLabel("00:00");
auto layout = new QHBoxLayout();
layout->addWidget(avatar);
auto centralColumn = new QVBoxLayout();
centralColumn->addWidget(title);
centralColumn->addWidget(subtitle);
layout->addItem(centralColumn);
layout->addWidget(time);
this->setLayout(layout);
}
void UserEntryWidget::setUserInfo(const UserInfo& user)
{
avatar->setPixmap(QPixmap::fromImage(user.getAvatar()));
title->setText(user.getTitle());
subtitle->setText(user.getSubtitle());
time->setText(user.getTime().toString("hh:mm"));
}
useritemdelegate.h
#ifndef USERITEMDELEGATE_H
#define USERITEMDELEGATE_H
#include <QStyledItemDelegate>
#include "userentrywidget.h"
class UserItemDelegate : public QStyledItemDelegate
{
public:
UserItemDelegate(QObject* parent = nullptr);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void setEditorData(QWidget* editor, const QModelIndex& index) const;
};
#endif // USERITEMDELEGATE_H
useritemdelegate.cpp
#include "useritemdelegate.h"
UserItemDelegate::UserItemDelegate(QObject* parent) : QStyledItemDelegate (parent)
{
}
QWidget* UserItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
if (index.data().canConvert<UserInfo>()) {
UserInfo user = qvariant_cast<UserInfo>(index.data());
auto editor = new UserEntryWidget(parent);
editor->setUserInfo(user);
return editor;
} else {
return QStyledItemDelegate::createEditor(parent, option, index);
}
}
void UserItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
if (index.data().canConvert<UserInfo>()) {
UserInfo user = qvariant_cast<UserInfo>(index.data());
UserEntryWidget* userEditor = qobject_cast<UserEntryWidget*>(editor);
userEditor->setUserInfo(user);
} else {
QStyledItemDelegate::setEditorData(editor, index);
}
}
main.cpp
#include <QApplication>
#include <QListView>
#include <QListWidget>
#include <QIcon>
#include <QLabel>
#include <QDebug>
#include "userentrywidget.h"
#include "useritemdelegate.h"
#include "userlistmodel.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<UserInfo>("UserInfo");
qDebug() << QMetaType::type("UserInfo");
auto lm = new UserListModel();
lm->insertRows(0, 5);
auto widget = new QListView();
widget->setModel(lm);
widget->setItemDelegate(new UserItemDelegate());
widget->resize(500, 300);
widget->show();
return a.exec();
}