我有一个QTableView
,我填充了QAbstractTableModel
。一列,比如第三列,应该包含一个QCheckBox
,我想为其显示两个图标,而不是QCheckBox
的标准外观,on
状态的一个图标和另一个off
州。
为此,我从QAbstractTableModel
派生了一个模型,并从QStyledItemDelegate
派生了一个委托。问题是我的模型setData
从未被调用过,唯一出现的图标就是off
。以下是我的测试实现的一些代码片段
MyModel.h :
#ifndef MYMODEL_H
#define MYMODEL_H
#include <vector>
#include <QAbstractTableModel>
class MyModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit MyModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool indexIsValid(const QModelIndex& index) const;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex& index, const QVariant& value, int role) override;
private:
std::vector<bool> _states;
};
#endif // MYMODEL_H
MyModel.cpp :
#include "MyModel.h"
MyModel::MyModel(QObject *parent) : QAbstractTableModel(parent)
{
_states.resize(5,false);
}
int MyModel::rowCount(const QModelIndex &parent) const
{
return 4;
}
int MyModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant MyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return QString("Col");
return QVariant();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index))
return QVariant();
if (role==Qt::DisplayRole)
{
if (index.column() != 2)
return QString("blabla");
}
else if (role==Qt::CheckStateRole)
{
if (index.column() == 2)
{
Qt::CheckState state = _states[index.row()] ? Qt::Checked : Qt::Unchecked;
return state;
}
}
return QVariant();
}
bool MyModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!indexIsValid(index))
return false;
if (role==Qt::CheckStateRole)
{
{
if (index.column()==2)
_states[index.row()] = value.toBool();
}
}
emit dataChanged(index,index);
return true;
}
bool MyModel::indexIsValid(const QModelIndex& index) const
{
return index.isValid() && index.row() < 5;
}
Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
{
if (!indexIsValid(index))
return Qt::ItemIsEnabled;
if (index.column() == 2)
return QAbstractTableModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
return QAbstractTableModel::flags(index);
}
MyDelegate.h :
#ifndef MYDELEGATE_H
#define MYDELEGATE_H
#include <QStyledItemDelegate>
#include <QModelIndex>
#include <QObject>
#include <QSize>
#include <QSpinBox>
#include <QIcon>
class MyDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit MyDelegate(QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
QIcon _icon;
};
#endif // MYDELEGATE_H
MyDelegate.cpp
#include "MyDelegate.h"
#include <QCheckBox>
#include <QPainter>
#include <QApplication>
#include <QStyleOptionViewItem>
MyDelegate::MyDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
_icon.addPixmap(QPixmap(":/selected.png"), QIcon::Normal, QIcon::On);
_icon.addPixmap(QPixmap(":/deselected.png"), QIcon::Normal, QIcon::Off);
}
void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() != 2)
QStyledItemDelegate::paint(painter,option,index);
else
{
bool value = index.model()->data(index).toBool();
QStyleOptionButton buttonVis;
buttonVis.rect = option.rect;
buttonVis.iconSize = QSize(10,10);
buttonVis.icon = _icon;
buttonVis.state |= QStyle::State_Enabled;
buttonVis.state |= value? QStyle::State_On : QStyle::State_Off;
buttonVis.features = QStyleOptionButton::None;
QApplication::style()->drawControl(QStyle::CE_PushButton,&buttonVis, painter);
}
}
你对我错过了什么让它有用吗?