QStyledItemDelegate制作卡片

QStyleItemDelegate介绍

QStyledItemDelegate 继承自 QAbstractItemDelegate,用于绘制QTableView、QListView等控件的单元格。单元格可自定义样式并且存放自定义数据。QStyledItemDelegate制作卡片_第1张图片
用QStyleItemDelegate制作的国家简介卡片,每个单元格可显示国旗图片、国家三字码、中文名、英文名。并且单元格不同状态(选中、鼠标悬浮)时样式不同。

一、重写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);
}

二、了解QStyleOptionViewItem

上述的paint函数中有一个重要的参数const QStyleOptionViewItem &option,他存放着单元格的状态、样式、属性等信息。我们来了解一下QStyleOptionViewItem :
QStyleOptionViewItem 继承自QStyleOption

QRect QStyleOption::rect

返回对象的QRect。

QStyle::State QStyleOption::state

此变量保存绘制控件时使用的样式标志。 状态种类有以下:

QStyle::State_None
QStyle::State_Active
QStyle::State_AutoRaise
QStyle::State_Children
QStyle::State_DownArrow
QStyle::State_Editing
QStyle::State_Enabled
QStyle::State_HasEditFocus
QStyle::State_HasFocus
QStyle::State_Horizontal
QStyle::State_KeyboardFocusChange
QStyle::State_MouseOver
QStyle::State_NoChange
QStyle::State_Off
QStyle::State_On
QStyle::State_Raised
QStyle::State_ReadOnly
QStyle::State_Selected
QStyle::State_Item
QStyle::State_Open
QStyle::State_Sibling
QStyle::State_Sunken
QStyle::State_UpArrow
QStyle::State_Mini
QStyle::State_Small

例子中我们使用了:QStyle::State_Selected 已选中状态、QStyle::State_MouseOver 鼠标悬浮状态。

三、加载QStyleItemDelegate

在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

四、运行程序

你可能感兴趣的:(QT,qt,开发语言)