目录
杂
Qt可作为数据可视化的一种解决方案。对此,常用的就是mvc架构了。较与常规wiget填充展示数据层次更加清晰。
何为
具体看下图
数据源:首先我们需要定制适合的数据结构,用个容器进行包裹即可
src_model:对于不同的view需要不同的model,我们对应继承并重写相关方法即可
proxy_model:代理model,用src_model作为model源;负责过滤【淘汰方法】{filterAcceptsRow,filterAcceptsColumn
}和排序【排序方法】{lessThan}
proxy_ui:代理ui,使用designer设计的ui,view最终展示的item
item_delegate:view的item代理,负责paint、create我们的proxy_ui
至于,这几者数据交互,基本由index和role完成
just do it
实现的效果
A图:数据从无到有的,添加过程,addData()
B图:更新数据,checkAble,
C图:实现排序
D图:编辑item
如何实现的呢,这里列出基本结构
- Model
// data
typedef struct _info{
QString name;
QString sex ;
bool protect;
QString desc;
bool checkable;
_info(){
name = "";
sex = "";
protect = false;
desc = "hello";
checkable = false;
}
} Info;
Q_DECLARE_METATYPE(Info)
// model
class MyModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit MyModel(QObject *parent = nullptr);
MyModel(const MyModel &other);
~MyModel();
// data 层面更新原始数据
void updateDaTa(const bool &checkabale);
// data 层面添加数据
void addData(QString const &name, QString const &sex, bool protect = false);
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
// 对于不同角色getData
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
// model 填充数据
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
// 角色名
virtual QHash<int, QByteArray> roleNames() const;
// 对应的item选项 care
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
private:
// 数据源
QList<Info> m_data;
};
Q_DECLARE_METATYPE(MyModel)
void MyModel::updateDaTa(const bool &checkabale)
{
beginResetModel();
// data
for(auto &one : m_data){
one.checkable = checkabale;
}
// core update model
endResetModel();
}
int MyModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_data.length();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || rowCount() < index.row() || index.row() < 0)
return QVariant();
int row = index.row();
Info item = m_data[row];
switch (role) {
case Qt::UserRole:
return item.name;
case Qt::UserRole+1:
return item.sex;
case Qt::UserRole+2:
return item.protect;
case Qt::UserRole+3:
return item.desc;
case Qt::UserRole+4:
return item.checkable;
default:
break;
}
return QVariant();
}
QHash<int, QByteArray> MyModel::roleNames() const
{
QHash<int,QByteArray> hash;
hash.insert(Qt::UserRole, "name");
hash.insert(Qt::UserRole+1, "sex");
hash.insert(Qt::UserRole+2, "protect");
hash.insert(Qt::UserRole+3, "desc");
hash.insert(Qt::UserRole+4, "checkable");
return hash;
}
bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::UserRole+3)
{
m_data[index.row()].desc = value.toString();
emit dataChanged(index, index);
return true;
}
if (index.isValid() && role == Qt::UserRole+4)
{
m_data[index.row()].checkable = value.toBool();
emit dataChanged(index, index);
return true;
}
return false;
}
Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
{
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ;
}
void MyModel::addData(const QString &name, const QString &sex, bool protect)
{
Info item;
item.name = name;
item.sex = sex;
item.protect = protect;
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_data << item;
endInsertRows();
}
- proxy_model
bool SortProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
QString sexLeft = left.data(Qt::UserRole+1).toString();
QString sexRight = right.data(Qt::UserRole+1).toString();
// M > F
if(sexLeft>sexRight){
return true;
}
else if(sexLeft == sexRight){
return left.data(Qt::UserRole).toString() > right.data(Qt::UserRole).toString();
}
else{
return false;
}
}
- itemDelegate
#define USE_HELP qDebug() << __FUNCTION__;
MyDelegate::MyDelegate(QObject *p)
:QStyledItemDelegate(p)
{
m_pDeleWidget = new DelegateWgt();
}
MyDelegate::~MyDelegate()
{
m_pDeleWidget->deleteLater();
m_pDeleWidget = nullptr;
}
void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(m_misEdit)
{
if(m_mEditingIndex == index)
{
return QStyledItemDelegate::paint(painter, option, index);
}
}
QString name = index.data(Qt::UserRole).toString();
QString sex = index.data(Qt::UserRole+1).toString();
bool protect = index.data(Qt::UserRole+2).toBool();
QString desc = index.data(Qt::UserRole+3).toString();
bool checkable = index.data(Qt::UserRole+4).toBool();
m_pDeleWidget->setName(name);
m_pDeleWidget->setSex(sex);
m_pDeleWidget->setProtect(protect);
m_pDeleWidget->setDesc(desc);
m_pDeleWidget->setCheckable(checkable);
m_pDeleWidget->resize(option.rect.size());
painter->save();
QPixmap pixmap(m_pDeleWidget->size());
m_pDeleWidget->render(&pixmap);
painter->drawPixmap(option.rect,pixmap);
painter->restore();
QStyledItemDelegate::paint(painter, option, index);
}
QSize MyDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(100,70);
}
QWidget *MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
USE_HELP
m_misEdit = true;
m_mEditingIndex = index;
DelegateWgt *deleGateWgt = new DelegateWgt(parent);
deleGateWgt->resize(option.rect.size());
return deleGateWgt;
}
void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
USE_HELP
DelegateWgt *srcWgt = static_cast<DelegateWgt*>(editor);
if(srcWgt){
QString name = index.data(Qt::UserRole).toString();
QString sex = index.data(Qt::UserRole+1).toString();
bool protect = index.data(Qt::UserRole+2).toBool();
QString desc = index.data(Qt::UserRole+3).toString();
bool checkable = index.data(Qt::UserRole+4).toBool();
srcWgt->setName(name);
srcWgt->setSex(sex);
srcWgt->setProtect(protect);
srcWgt->setDesc(desc);
srcWgt->setCheckable(checkable);
}
}
void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
USE_HELP
DelegateWgt *srcWgt = static_cast<DelegateWgt*>(editor);
if(srcWgt){
model->setData(index, srcWgt->getName(), Qt::UserRole);
model->setData(index, srcWgt->getSex(), Qt::UserRole+1);
model->setData(index, false, Qt::UserRole+2);
model->setData(index,srcWgt->getDesc(),Qt::UserRole+3);
model->setData(index, srcWgt->getCheckable(), Qt::UserRole+4);
}
m_misEdit = false;
}
void MyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
USE_HELP
DelegateWgt *srcWgt = static_cast<DelegateWgt*>(editor);
if(srcWgt){
srcWgt->setGeometry(option.rect);
}
}
- 代理ui
其就是传统designer设计的widget即可
- using
// model
m_pModel = new MyModel;
// proxy_model
m_pSortModelProxy = new SortProxy;
m_pSortModelProxy->setSourceModel(m_pModel);
// itemDelegat
m_pDelegate = new MyDelegate;
// view
ui->listView->setModel(m_pSortModelProxy);
ui->listView->setItemDelegate(m_pDelegate);
// add
m_pModel->addData
// updata
m_pModel->updateDaTa
// sort
m_pSortModelProxy->sort(0)
Care
其实,主要是对于Qt这种mvc架构中index和role的理解,主要model中的这几个函数,数据导向是一个怎样的情况。
Qes
如何,实现类widget那样直接可以编辑item,即可见即可编辑?
版权声明:本文为qq_39175540原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。