Qt : 自定义委托类.子类化QStyledItemDelegate

由于QListWidget的子项都是单列的.所以能显示的不太多,但是如果使用listWidget->setItemWidget();方法的话,内存的开销又有点大.所以有一些信息可以用画的方式绘图出来,先看下简单的效果:

Qt : 自定义委托类.子类化QStyledItemDelegate_第1张图片

像QListWidget,QTableWidget这些都属于视图类.默认都带有基础的Delegate.当我们想要给视图的子项更多种的显示方式的话,子类化QStyledItemDelegate或QItemDelegate都可以,下面以子类化QStyledItemDelegate做例子:

#ifndef MYITEMDELEGATE_H
#define MYITEMDELEGATE_H

#include 
#include 
//子类化的委托类.
class MyItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyItemDelegate(QWidget *parent);
    ~MyItemDelegate();
protected:
    //重写这两个虚函数.注意: const不要忘,否则不属于虚函数的重写.
    virtual QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const;
    virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
private:

};

#endif // MYITEMDELEGATE_H
#include "MyItemDelegate.h"

MyItemDelegate::MyItemDelegate(QWidget *parent)
    : QStyledItemDelegate(parent)
{

}

MyItemDelegate::~MyItemDelegate()
{

}
//需要重写调整的尺寸的方法.注意:调整的是子项的尺寸.
QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    //获得原来的视图参数.
    QSize  size = QStyledItemDelegate::sizeHint(option, index);
    size.setHeight(80);
    return size;
}
void MyItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    //返回项的矩形边框.
    QRect rect = option.rect;

    //当项被选中时.
    if (option.state & QStyle::State_Selected)
    {
        painter->setBrush(Qt::cyan);
        painter->drawRect(rect);
    }

    //获取项的数据.
    QString name = index.data(Qt::DisplayRole).toString();
    QString phone = index.data(Qt::UserRole).toString();
    QString address = index.data(Qt::UserRole + 1).toString();

    //画名字.
    painter->drawText(rect.topLeft() + QPoint(20, 20), QString::fromLocal8Bit("姓名:%1").arg(name));

    //画电话.
    painter->drawText(rect.topLeft() + QPoint(20, 40), QString::fromLocal8Bit("电话:%1").arg(phone));

    //画地址.
    painter->drawText(rect.topLeft() + QPoint(20, 60), QString::fromLocal8Bit("地址:%1").arg(address));
}
#include "c.h"

c::c(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    m_precRow  = -1;

    //先加入四个数据项.
    addItem("test1", "100000000000",QString::fromLocal8Bit("北京"));
    addItem("test2", "100000000001", QString::fromLocal8Bit("杭州"));
    addItem("test3", "100000000002", QString::fromLocal8Bit("厦门"));
    addItem("test4", "100000000003", QString::fromLocal8Bit("上海"));

    //当项被点击时发出的信号.
    connect(ui.listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(detailDisplaySlot(QListWidgetItem*)));
}

c::~c()
{

}
void c::addItem(QString name, QString phone, QString address)
{
    //创建项.
    QListWidgetItem *item = new QListWidgetItem();
    //设置项的数据.
    item->setData(Qt::DisplayRole,name);
    item->setData(Qt::UserRole, phone);
    item->setData(Qt::UserRole + 1, address);
    //设置项的尺寸.
    item->setSizeHint(QSize(ui.listWidget->width(),40));

    ui.listWidget->addItem(item);
}
void c::detailDisplaySlot(QListWidgetItem* item)
{
    //当点击项改变时,之前的项的委托情况需要改变.还要改变尺寸.
    if (m_precRow >= 0)
    {
        ui.listWidget->setItemDelegateForRow(m_precRow, new QStyledItemDelegate());
        ui.listWidget->item(m_precRow)->setSizeHint(QSize(ui.listWidget->width(), 40));
    }
    //获取点击项的行数.
    m_precRow = ui.listWidget->row(item);
    //设置点击项的当前行使用自己定义的委托.
    ui.listWidget->setItemDelegateForRow(ui.listWidget->row(item), new MyItemDelegate(ui.listWidget));
    //重新设置大小.
    ui.listWidget->item(m_precRow)->setSizeHint(QSize(ui.listWidget->size().width(),80));
}


#ifndef C_H
#define C_H

#include 
#include "ui_c.h"
#include "MyItemDelegate.h"

class c : public QWidget
{
    Q_OBJECT

public:
    c(QWidget *parent = 0);
    ~c();
    void addItem(QString,QString,QString);
private slots:
    void detailDisplaySlot(QListWidgetItem*);
private:
    Ui::cClass ui;
    int m_precRow = -1;
};

#endif // C_H

这样一来就大功告成了,当然listWidget->setItemWidget();方法也可以实现这样的场景,但是如果子项的数目一旦非常的话,对内存的开销是很大的!

你可能感兴趣的:(Qt,Qt)