QListView 自定义delegate和model, 添加checkbox、按钮、文本
主要功能:利用QListview显示自定的model数据和内容;显示内容包括QCheckbox,QLabel。实现原理:QCheckbox在页面显示,就是根据model数据中的按钮的选中状态来显示对应图片, 然后画出对应的图片;同样道理,我们可以添加各种自定义button,自定义button的各种状态图片。效果如图:代码:头文件:#ifndef MAINWINDOW_H#define MAINWI
·
主要功能:利用QListview显示自定的model数据和内容;显示内容包括QCheckbox, QLabel。
实现原理:QCheckbox在页面显示,就是根据model数据中的按钮的选中状态来显示对应图片, 然后画出对应的图片;同样道理,我们可以添加各种自定义button,自定义button的各种状态图片。
效果如图:
代码:
头文件:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QAbstractListModel>
#include <QStyledItemDelegate>
#include <QListView>
struct CustomData
{
bool m_isSelect;
QString m_txt;
};
class CustomListModel : public QAbstractListModel
{
Q_OBJECT
public:
CustomListModel();
~CustomListModel();
void insertData(CustomData data);
//必须实现的函数
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
private:
QList<CustomData> m_listData;
};
class CustomDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
CustomDelegate();
~CustomDelegate();
//描绘画面显示
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//处理鼠标事件
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QListView *m_list;
CustomListModel *m_model;
CustomDelegate * m_delegate;
};
#endif // MAINWINDOW_H
cpp文件:
#include <QPainter>
#include <QDebug>
#include <QMouseEvent>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setGeometry(200,200,800,480);
m_list = new QListView(this);
m_list->setGeometry(0,0,300,200);
m_model = new CustomListModel();
//添加测试数据库
for(int i = 0; i < 5; i++)
{
CustomData data;
data.m_isSelect = (i%2==0);
data.m_txt = QString("This is %1").arg(QString::number(i+1));
m_model->insertData(data);
}
m_delegate = new CustomDelegate();
m_list->setModel(m_model);
m_list->setItemDelegate(m_delegate);
m_list->setMouseTracking(true);
}
MainWindow::~MainWindow()
{
}
CustomListModel::CustomListModel()
{
}
CustomListModel::~CustomListModel()
{
}
void CustomListModel::insertData(CustomData data)
{
m_listData.push_back(data);
}
int CustomListModel::rowCount(const QModelIndex &parent) const
{
return m_listData.size();
}
QVariant CustomListModel::data(const QModelIndex &index, int role) const
{
QVariant ret;
int row = index.row();
if(row>=m_listData.size()||(!index.isValid()))
{
return QVariant();
}
CustomData tmpData = m_listData.at(row);
// 下面的role要和setData中的role一一对应;
switch(role) {
case Qt::UserRole+1:
ret = tmpData.m_isSelect;
break;
case Qt::UserRole+2:
ret = tmpData.m_txt;
break;
default :
break;
}
return ret;
}
bool CustomListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
bool ret = false;
int row = index.row();
if(row>=m_listData.size()||(!index.isValid()))
{
return false;
}
CustomData tmpData = m_listData.at(row);
switch(role) {
case Qt::UserRole+1:
tmpData.m_isSelect = value.toBool();
ret = true;
break;
case Qt::UserRole+2:
tmpData.m_txt = value.toString();
ret = true;
break;
default :
break;
}
m_listData.replace(row, tmpData);
return ret;
}
CustomDelegate::CustomDelegate()
{
}
CustomDelegate::~CustomDelegate()
{
}
void CustomDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QRect retc = option.rect;
//这里取的数据 对应model里面的role
bool isSelect = index.data(Qt::UserRole+1).toBool();
QString txt = index.data(Qt::UserRole+2).toString();
//qDebug() << "paint data isSelect" << isSelect << "txt" << txt;
QStyleOptionViewItem viewoption(option);
initStyleOption(&viewoption, index);
if(option.state.testFlag(QStyle::State_HasFocus))
{
viewoption.state = viewoption.state^QStyle::State_HasFocus;
}
QStyledItemDelegate::paint(painter, viewoption, index);
//画按钮
{
QRect checboxRec(retc.left() + 10, retc.top() + (retc.height()-20)/2, 20, 20); //左边距10,竖直方向居中
if(isSelect)
{
QPixmap pix("G:\\QT_Project\\listViewModelDelegate\\fxk_not.png");
painter->drawPixmap(checboxRec, pix);
}
else
{
QPixmap pix("G:\\QT_Project\\listViewModelDelegate\\fxk_ok.png");
painter->drawPixmap(checboxRec, pix);
}
}
//画txt
{
painter->save();
//设置字体,颜色
QFont font;
font.setFamily("Microsoft YaHei");
font.setPixelSize(10);
painter->setFont(font);
QRect txtRec(retc.left() + 50, retc.top(), retc.width()-100, retc.height());
painter->drawText(txtRec, Qt::AlignCenter, txt);
painter->restore();
}
}
bool CustomDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
QRect retc = option.rect;
//对应上面画的checkbox的retc
QRect checboxRec(retc.left() + 10, retc.top() + (retc.height()-20)/2, 20, 20);
//按钮点击事件;
QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
if(checboxRec.contains(mevent->pos()) && event->type() == QEvent::MouseButtonPress)
{
bool value = model->data(index, Qt::UserRole+1).toBool();
model->setData(index, !value, Qt::UserRole+1);
model->dataChanged(index, index);
//此处可以添加自定义信号,即使checbox点击信号;
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
总结:
按钮的显示,归根到底就是根据鼠标事件选择显示对应的图片;主要函数就是delegate中的paint函数和editorEvent函数;paint负责渲染,editorEvent负责鼠标事件;根据此框架,可以满足绝大部分的定制需求;
转载请注明出处;
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)