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

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

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

#ifndef MYITEMDELEGATE_H #define MYITEMDELEGATE_H#include #include //子类化的委托类. class MyItemDelegate : public QStyledItemDelegate { Q_OBJECTpublic: 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 { //获得原来的视图参数. QSizesize = 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_OBJECTpublic: 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(); 方法也可以实现这样的场景,但是如果子项的数目一旦非常的话,对内存的开销是很大的!

    推荐阅读