赞
踩
首先,先上效果图:
点击listView中的按钮,分别有:clicked row index = 0 和 clicked row index = 1 的打印,也就是说可以判断item中哪个按钮被按下。
第一步
当然是先创建一个widget的project,再往ui文件中拖入一个listView,
点击栅格布局,如图:
第二步
自定义一个委托类,这个类主要用来在listView中绘制自己想要的元素,看了效果图就知道,listView中主要是有按钮和文字这两个元素,那么我们只需要每一个item中绘制一个文本和一个按钮即可,看代码:
.h
#ifndef LISTVIEWDELEGATE_H #define LISTVIEWDELEGATE_H #include <QStyledItemDelegate> #include <QPainter> typedef struct { //文字 QString titleText; //开关状态 QString state; //按钮 QWidget *widget; } itemProperty; Q_DECLARE_METATYPE(itemProperty) class listViewDelegate : public QStyledItemDelegate { public: explicit listViewDelegate(QObject *parent = nullptr); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; #endif // LISTVIEWDELEGATE_H
.cpp
#include "listviewdelegate.h" //按钮的高、宽以及坐标点 #define WIDGET_LEFT_MARGIN 270 #define WIDGET_TOP_MARGIN 20 #define WIDGET_WIDTH 80 #define WIDGET_HEIGHT 50 //每个item的高度 #define LISTVIEW_ITEM_HEIGHT 100 //分割item的线的颜色 #define LINE_COLOR "#CECECE" //文字的颜色 #define TEXT_COLOR "#130c0e" //文字的大小 #define TEXT_SIZE 15 listViewDelegate::listViewDelegate(QObject *parent) : QStyledItemDelegate(parent) { } void listViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.isValid()) { QVariant dataVar = index.data(Qt::UserRole + 1); itemProperty itemData = dataVar.value<itemProperty>(); painter->save(); //每个item的区域 QRectF rect; rect.setX(option.rect.x()); rect.setY(option.rect.y()); rect.setWidth(option.rect.width() - 1); rect.setHeight(option.rect.height() - 1); //text的区域 QRect textRect = QRect( 0 + 10, rect.top() + WIDGET_TOP_MARGIN, 100, WIDGET_HEIGHT); painter->setPen(QPen(TEXT_COLOR)); painter->setFont(QFont("SourceHanSansCN-Normal", TEXT_SIZE)); painter->drawText(textRect, itemData.titleText); //widget的区域 QRect widgetRect = QRect( WIDGET_LEFT_MARGIN, rect.top() + WIDGET_TOP_MARGIN, WIDGET_WIDTH, WIDGET_HEIGHT); if (itemData.widget) { itemData.widget->setGeometry(widgetRect); itemData.widget->show(); } //设置线的颜色 painter->setPen(QPen(QColor(LINE_COLOR))); //两点确定一条直线 //线的起点:x一定是0,并且每一条线的x是一样的,y是每个item的顶部坐标 + 1 //线的终点:y一定是和起点的y是一样的,那么只需要给出x的长度,线的长度就是每个item的宽度 painter->drawLine(QPointF(0, rect.bottom() - 1), QPointF(rect.width(), rect.bottom() - 1)); } painter->restore(); } QSize listViewDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index) return QSize(option.rect.width(), LISTVIEW_ITEM_HEIGHT); }
第三步
委托类已经写好了,剩下的就是主UI的逻辑部分了。在主UI的头文件中包含一下自定义的委托类:
#include "listviewdelegate.h"
刚才在委托类中定义了一个结构体,这个结构体就包含了我们所需要的所有元素了,那么在头文件中也要定义一个:
//因为一个listView一般不会只有一个item,
//一个结构体只对应一个item,
//很多个item就是很多的结构体,
//所以弄成一个list
QList<itemProperty> listItems;
//记得包含头文件
QStandardItemModel *listModel;
listViewDelegate *listItemDelegate;
最后,在主UI 的.cpp中
#define STYLE_OFF_STR "QPushButton{border-image: url(:/myIcon/switch/off-.png)};" #define STYLE_ON_STR "QPushButton{border-image: url(:/myIcon/switch/on-.png)};" 构造函数中加入: listModel = NULL; listItemDelegate = NULL; listItems = { {"按钮0", NULL}, {"按钮1", NULL}, }; listModel = new QStandardItemModel(this); for(int listRow=0; listRow<listItems.count(); listRow++) { QStandardItem *pItem = new QStandardItem; //定义一个按钮(可以根据需求不同定义不同的控件) QPushButton *widget = new QPushButton(""); //设置按钮的属性,在这里设置了按钮的id, //可以在槽函数中根据这个按钮的id区分出具体是哪一个按钮按下 widget->setProperty("BtnID", QString("%1").arg(listRow)); //设置父级 widget->setParent(ui->listView); listItems[listRow].widget = widget; //设置风格 widget->setStyleSheet(STYLE_OFF_STR); //下一次开关状态 listItems[listRow].state = "1"; //关联槽函数,可以几个按钮关联同一个槽函数, //在槽函数中根据BtnID区分出具体是哪一个按钮按下,再执行相应的代码 connect(widget, SIGNAL(clicked()), this, SLOT(slotListviewBtnCheckin())); pItem->setData(QVariant::fromValue(listItems.at(listRow)), Qt::UserRole + 1); listModel->appendRow(pItem); } listItemDelegate = new listViewDelegate(this); ui->listView->setItemDelegate(listItemDelegate); ui->listView->setModel(listModel); connect(ui->listView, SIGNAL(clicked(QModelIndex)), this, SLOT(slotlistViewForCheckin(QModelIndex))); //禁止编辑 ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers); /***************************按钮关联的槽函数************************************/ void listViewWidget::slotListviewBtnCheckin() { QPushButton *btn = dynamic_cast<QPushButton*> (sender()); if(btn != Q_NULLPTR) { //取出按钮的id属性 int index = btn->property("BtnID").toInt(); switch(index) { //根据BtnID不同,执行相应的代码 case 0: break; case 1: break; default: break; } //按钮图片更新 if(listItems[index].state.compare("0") == 0) { listItems[index].widget->setStyleSheet(STYLE_OFF_STR); listItems[index].state = "1"; } else { listItems[index].widget->setStyleSheet(STYLE_ON_STR); listItems[index].state = "0"; } qDebug() << "clicked row index = " << index; } }
点击运行:
Nice,歪瑞故德
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。