QStyledItemDelegate 继承自 QAbstractItemDelegate,用于绘制QTableView、QListView等控件的单元格。单元格可自定义样式并且存放自定义数据。
用QStyleItemDelegate制作的国家简介卡片,每个单元格可显示国旗图片、国家三字码、中文名、英文名。并且单元格不同状态(选中、鼠标悬浮)时样式不同。
定义结构体:itemdef.h
#ifndef ITEMDEF_H
#define ITEMDEF_H
#include
#include
struct ItemData{
QString dm;
QString cname;
QString ename;
QPixmap tp;
};
Q_DECLARE_METATYPE(ItemData)
#endif // ITEMDEF_H
h
#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H
#include
#include
#include
#include "itemdef.h"
class ItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
signals:
public:
explicit ItemDelegate(QObject *parent = 0);
~ItemDelegate();
//重写重画函数
void paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
private:
};
#endif // ITEMDELEGATE_H
cpp
#include "itemdelegate.h"
#include
#include
#include
ItemDelegate::ItemDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
}
ItemDelegate::~ItemDelegate()
{
}
void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.isValid())
{
//获取单元格中数据
QVariant variant = index.data(Qt::UserRole+1);
ItemData data = variant.value<ItemData>();
//单元格边框,注意要比单元格总大小略小一些,不然绘制的边框线刚好处于外缘会显示不全
QRect rect = QRect(option.rect.left()+3,option.rect.top()+3,option.rect.width()-6,option.rect.height()-6);
//根据不同状态,绘制不同颜色边框
if(option.state.testFlag(QStyle::State_Selected))
{
painter->setPen(QPen(Qt::blue));
painter->setBrush(QColor(229, 241, 255));
painter->drawRoundedRect(rect,7,7);
}
else if(option.state.testFlag(QStyle::State_MouseOver))
{
painter->setPen(QPen(Qt::green));
painter->setBrush(Qt::NoBrush);
painter->drawRoundedRect(rect,7,7);
}
else{
painter->setPen(QPen(Qt::gray));
painter->setBrush(Qt::NoBrush);
painter->drawRoundedRect(rect,7,7);
}
//绘制数据位置
QRect dmRect = QRect(210+option.rect.left(),10+option.rect.top(),330,50);
QRect cnameRect = QRect(210+option.rect.left(),65+option.rect.top(),330,40);
QRect enameRect = QRect(210+option.rect.left(),100+option.rect.top(),330,40);
QRect picRect = QRect(option.rect.left()+5,option.rect.top()+10,210,120);
painter->setPen(QPen(Qt::black));
painter->setFont(QFont("Times", 22, QFont::Bold));
painter->drawText(dmRect,Qt::AlignCenter,data.dm); //国家代码
painter->setFont(QFont("微软雅黑", 12));
painter->drawText(cnameRect,Qt::AlignCenter,data.cname); //国家中文名
painter->setFont(QFont("Times", 10));
painter->drawText(enameRect,Qt::AlignCenter,data.ename); //国家英文名
painter->drawPixmap(picRect,data.tp);
}
}
//返回单元格大小,此函数无需手动调用
QSize ItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(550, 140);
}
上述的paint函数中有一个重要的参数const QStyleOptionViewItem &option,他存放着单元格的状态、样式、属性等信息。我们来了解一下QStyleOptionViewItem :
QStyleOptionViewItem 继承自QStyleOption
返回对象的QRect。
此变量保存绘制控件时使用的样式标志。 状态种类有以下:
例子中我们使用了:QStyle::State_Selected 已选中状态、QStyle::State_MouseOver 鼠标悬浮状态。
在ui中拉入一个QListVew。
h
#include
#include
#include
#include
#include
#include "itemdef.h"
#include "itemdelegate.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
//点击单元格的槽函数
void on_listView_clicked(const QModelIndex &index);
protected:
//将生成卡片的代码放在resizeevent里可以随界面大小动态调整布局
void resizeEvent(QResizeEvent *event);
private:
Ui::Widget *ui;
ItemDelegate *m_delegate;
QStandardItemModel *m_model;
};
#endif // WIDGET_H
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
m_delegate = new ItemDelegate(this);
m_model = new QStandardItemModel;
ui->listView->setItemDelegate(m_delegate);//绑定delegate
ui->listView->setSpacing(10);//设置卡片的间隔
ui->listView->setModel(m_model);
ui->listView->setViewMode(QListView::IconMode);
ui->listView->setDragEnabled(false);
}
Widget::~Widget()
{
delete ui;
}
void Widget::resizeEvent(QResizeEvent *event)
{
QFile file("GJDQTable.txt");//从文件中读取数据
file.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
QStandardItem *item = new QStandardItem;
ItemData itemdata;
itemdata.dm=line.mid(0,line.indexOf(","));
line.remove(0,line.indexOf(",")+1);
itemdata.cname=line.mid(0,line.indexOf(","));
line.remove(0,line.indexOf(",")+1);
itemdata.ename=line.mid(0,line.indexOf(","));
itemdata.tp=QPixmap(":/pic/res/1.png");
item->setData(QVariant::fromValue(itemdata),Qt::UserRole+1);
m_model->appendRow(item);
}
}
//点击卡片时打印相应的卡片信息(获取当前点击卡片的信息)
void Widget::on_listView_clicked(const QModelIndex &index)
{
QStandardItem *item = new QStandardItem;
item = m_model->item(index.row(),index.column());
QVariant v = item->data();
ItemData data = v.value<ItemData>();
qDebug()<<data.dm<<data.cname<<data.ename;
}
#ifndef WIDGET_H
#define WIDGET_H