我在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();
}