QStyledItemDelegate是所有Qt item視圖的默認(rèn)委托,在創(chuàng)建它們時就會被安裝在它們上面。
QStyledItemDelegate類是模型/視圖類之一,是Qt模型/視圖框架的一部分。委托允許項目的顯示和編輯獨(dú)立于模型和視圖進(jìn)行開發(fā)。
模型中數(shù)據(jù)項的數(shù)據(jù)被賦值為ItemDataRole;每個物品可以為每個角色存儲一個QVariant。QStyledItemDelegate實(shí)現(xiàn)了用戶所期望的最常見數(shù)據(jù)類型的顯示和編輯,包括布爾值、整數(shù)和字符串。
根據(jù)數(shù)據(jù)在模型中的角色不同,數(shù)據(jù)將以不同的方式繪制。
繼承QStyledItemDelegate需要重寫的四個方法:
//返回用于編輯由索引指定的項的小部件
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
//從模型索引指定的數(shù)據(jù)模型項設(shè)置要由編輯器顯示和編輯的數(shù)據(jù),默認(rèn)實(shí)現(xiàn)將數(shù)據(jù)存儲在editor小部件的user屬性中
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
//從editor小部件獲取數(shù)據(jù),并將其存儲在項目索引處的指定模型中,默認(rèn)實(shí)現(xiàn)從editor小部件的user屬性獲取要存儲在數(shù)據(jù)模型中的值
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
//更新由索引指定的項的編輯器
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
首先要繼承QStyledItemDelegate,并實(shí)現(xiàn)上面提到的四個方法。
代碼示例:
CustomStyledItem.h
#include <QObject>
#include <QStyledItemDelegate>
enum COLUMN_HEAD_INDEX {
CheckBox = 0,
Id = 1,
Format=2,
Type=3,
SendMode = 4,
Length=5,
Data=6,
SendTimes=7,
Interval=8,
Count = 9,
CANType = 10,
BRS = 11
};
class CustomStyledItem : public QStyledItemDelegate
{
public:
explicit CustomStyledItem(QObject* parent, int channel);
CustomStyledItem();
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
private :
int channel ;
};
CustomStyledItem.cpp
#include "CustomStyledItem.h"
#include <QCheckBox>
#include <QComboBox>
#include <QDebug>
#include "DevCan.h"
CustomStyledItem::CustomStyledItem(QObject* parent, int channel) : QStyledItemDelegate(parent), channel(channel)
{
}
CustomStyledItem::CustomStyledItem()
{
}
QWidget* CustomStyledItem::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
const QString style = R"(QCheckBox {padding-left: 4px; background-color: white; })";
QCheckBox* cbBox;
QComboBox* cb;
switch(index.column()) {
case CheckBox:
cbBox = new QCheckBox(parent);
cbBox->setStyleSheet(style);
return cbBox;
break;
case Id:
break;
case Format:
cb = new QComboBox(parent);
if(((DevCan::instance().getDevType() == VCI_USBCANFD_II) ||
(DevCan::instance().getDevType() == VCI_USBCANFD_I)) &&
(DevCan::instance().getChannelType(channel) == CANFD_CH)) {
cb->addItem(tr("Data Frame"), 0);
} else {
cb->addItem(tr("Data Frame"), 0);
cb->addItem(tr("Remote Frame"), 1);
}
return cb;
break;
case Type:
cb = new QComboBox(parent);
cb->addItem(tr("Standard Frame"), 0);
cb->addItem(tr("Extend Frame"), 1);
return cb;
break;
case SendMode:
cb = new QComboBox(parent);
cb->addItem(tr("Normal Send"), 0);
cb->addItem(tr("Single Send"), 1);
cb->addItem(tr("Send & Receive"), 2);
cb->addItem(tr("Single Send&Rec"), 3);
return cb;
break;
case Length:
break;
case Data:
break;
case SendTimes:
break;
case Interval:
break;
case Count:
break;
case CANType:
break;
case BRS:
break;
default:
break;
}
return NULL;
}
void CustomStyledItem::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QCheckBox* cbWidget;
QComboBox* cb;
int formatIndex;
switch(index.column()) {
case CheckBox:
cbWidget = dynamic_cast<QCheckBox*>(editor);
cbWidget->setChecked(index.data(Qt::DisplayRole).toString() == "Yes");
break;
case Id:
break;
case Format:
cb = dynamic_cast<QComboBox*>(editor);
cb->setCurrentIndex(index.data(Qt::DisplayRole).toBool()?0:1);
break;
case Type:
cb = dynamic_cast<QComboBox*>(editor);
cb->setCurrentIndex(index.data(Qt::DisplayRole).toBool()?0:1);
break;
case SendMode:
cb = dynamic_cast<QComboBox*>(editor);
cb->setCurrentIndex(index.data(Qt::DisplayRole).toBool()?0:1);
break;
case Length:
break;
case Data:
break;
case SendTimes:
break;
case Interval:
break;
case Count:
break;
case CANType:
break;
case BRS:
break;
default:
break;
}
}
void CustomStyledItem::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
QComboBox* cb;
bool state;
switch(index.column()) {
case CheckBox:
state = dynamic_cast<QCheckBox*>(editor)->isChecked();
//阻止模型發(fā)出信號
model->blockSignals(true);
model->setData(index, state ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
//模型可以發(fā)出信號
model->blockSignals(false);
model->setData(index, state, Qt::UserRole);
break;
case Id:
break;
case Format:
cb = dynamic_cast<QComboBox*>(editor);
model->setData(index, cb->currentText(), Qt::EditRole);
break;
case Type:
cb = dynamic_cast<QComboBox*>(editor);
model->setData(index, cb->currentText(), Qt::EditRole);
break;
case SendMode:
cb = dynamic_cast<QComboBox*>(editor);
model->setData(index, cb->currentText(), Qt::EditRole);
break;
case Length:
break;
case Data:
break;
case SendTimes:
break;
case Interval:
break;
case Count:
break;
case CANType:
break;
case BRS:
break;
default:
break;
}
}
void CustomStyledItem::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
editor->setGeometry(option.rect);
}
那么我們?nèi)绾问褂眠@個類呢,廢話不多說,直接上代碼,相信大家一看就全都明白了。
首先呢,我們將表格進(jìn)行初始化,這是在你的項目代碼中完成的,如MainWindow.cpp
void BottomTableView::initUI()
{
//這個就是關(guān)鍵方法了,這行代碼的意思是,將第1列添加一個自定義的小部件,就是我們上面創(chuàng)建的復(fù)選框
ui->tableViewBottom->setItemDelegateForColumn(0, new CustomStyledItem(ui->tableViewBottom, channel));
//第3列
ui->tableViewBottom->setItemDelegateForColumn(2, new CustomStyledItem(ui->tableViewBottom, channel));
//第4列
ui->tableViewBottom->setItemDelegateForColumn(3, new CustomStyledItem(ui->tableViewBottom, channel));
//第5列
ui->tableViewBottom->setItemDelegateForColumn(4, new CustomStyledItem(ui->tableViewBottom, channel));
modelBottom = new QStandardItemModel(ui->tableViewBottom);
if(((DevCan::instance().getDevType() == VCI_USBCANFD_II) ||
(DevCan::instance().getDevType() == VCI_USBCANFD_I)) &&
(DevCan::instance().getChannelType(channel) == CANFD_CH)) {
modelBottom->setHorizontalHeaderLabels(QStringList()<<tr(" ")<<tr("Id")<<tr("Format")<<tr("Type")<<tr("SendMode")
<<tr("Length")<<tr("Data(HEX)")<<tr("Send Times")<<tr("Interval(ms)")
<<tr("Count")<<tr("CANType")<<tr("BRS"));
} else {
modelBottom->setHorizontalHeaderLabels(QStringList()<<tr(" ")<<tr("Id")<<tr("Format")<<tr("Type")
<<tr("SendMode")<<tr("Length")<<tr("Data(HEX)")<<tr("Send Times")
<<tr("Interval(ms)")<<tr("Count"));
}
ui->tableViewBottom->setModel(modelBottom);
// //隱藏垂直表頭
ui->tableViewBottom->verticalHeader()->setVisible(false);
//設(shè)置表格的網(wǎng)格線風(fēng)格為自定義虛線風(fēng)格
ui->tableViewBottom->setGridStyle(Qt::CustomDashLine);
//開啟交替行顏色
// ui->tableViewBottom->setAlternatingRowColors(true);
//設(shè)置選擇模式為擴(kuò)展選擇,這意味著用戶可以選擇多個連續(xù)或不連續(xù)的行和列
// ui->tableViewBottom->setSelectionMode(QAbstractItemView::ExtendedSelection);
//設(shè)置選擇行為為選擇行,這意味著當(dāng)用戶點(diǎn)擊表格的任何地方時,整行都會被選中
// ui->tableViewBottom->setSelectionBehavior(QAbstractItemView::SelectRows);
//設(shè)置編輯觸發(fā)器為無,這意味著表格不應(yīng)在用戶進(jìn)行任何操作時進(jìn)入編輯模式
// ui->tableViewBottom->setEditTriggers(QAbstractItemView::NoEditTriggers);
//設(shè)置表格的框架形狀為矩形框
// ui->tableViewBottom->setFrameShape(QFrame::Box);
//設(shè)置表格框架的陰影為下沉樣式,這通常會使表格看起來更立體
// ui->tableViewBottom->setFrameShadow(QFrame::Sunken);
//設(shè)置列寬
ui->tableViewBottom->horizontalHeader()->resizeSection(0, 50);
ui->tableViewBottom->horizontalHeader()->resizeSection(1, 100);
ui->tableViewBottom->horizontalHeader()->resizeSection(2, 150);
ui->tableViewBottom->horizontalHeader()->resizeSection(3, 150);
ui->tableViewBottom->horizontalHeader()->resizeSection(4, 200);
ui->tableViewBottom->horizontalHeader()->resizeSection(5, 80);
ui->tableViewBottom->horizontalHeader()->resizeSection(6, 150);
ui->tableViewBottom->horizontalHeader()->resizeSection(7, 150);
ui->tableViewBottom->horizontalHeader()->resizeSection(8, 150);
ui->tableViewBottom->horizontalHeader()->resizeSection(9, 150);
if(((DevCan::instance().getDevType() == VCI_USBCANFD_II) ||
(DevCan::instance().getDevType() == VCI_USBCANFD_I)) &&
(DevCan::instance().getChannelType(channel) == CANFD_CH)) {
ui->tableViewBottom->horizontalHeader()->resizeSection(10, 100);
ui->tableViewBottom->horizontalHeader()->resizeSection(11, 100);
}
//將表格的水平表頭的最后一個section設(shè)置為可拉伸
ui->tableViewBottom->horizontalHeader()->setStretchLastSection(true);
//取消水平表頭的高亮
ui->tableViewBottom->horizontalHeader()->setHighlightSections(false);
//水平表頭對其方式
ui->tableViewBottom->horizontalHeader()->setDefaultAlignment(Qt::AlignVCenter);
//隱藏垂直表頭
// ui->tableViewBottom->verticalHeader()->setVisible(false);
//垂直表頭對其方式居中對齊
ui->tableViewBottom->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
//設(shè)置行高
ui->tableViewBottom->verticalHeader()->setDefaultSectionSize(30);
//垂直表頭的大小調(diào)整為適應(yīng)其內(nèi)容
ui->tableViewBottom->verticalHeader()->resizeSections(QHeaderView::ResizeToContents);
}
表格初始化好了,接下來就是像表格上添加數(shù)據(jù)了,請看下面代碼
這里,我用到了QSettings 來進(jìn)行數(shù)據(jù)的存儲,并取用,這部分知識在之后的文章中會再次提到的。
void BottomTableView::loadSendMsg()
{
//先清空
modelBottom->removeRows(0, modelBottom->rowCount());
int size = 0;
int colNum ;
QString applicationName = QString("%1_%2").arg("BASESEND", QString::number(channel));
QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Tegcan", applicationName);
if(((DevCan::instance().getDevType() == VCI_USBCANFD_II) ||
(DevCan::instance().getDevType() == VCI_USBCANFD_I)) &&
(DevCan::instance().getChannelType(channel) == CANFD_CH)) {
size = settings.beginReadArray("sendMsgsFD");
colNum = 12;
} else {
size = settings.beginReadArray("sendMsgs");
colNum = 10;
}
if(size == 0) {
return;
}
QString idStr="";
QString externFlag = "";
QString remoteFlag = "";
QString sendModeStr = "";
QString canTypeStr = "";
QString brsStr = "";
for(int row=0; row<size; row++) {
settings.setArrayIndex(row);
for(int col = 0; col< colNum; col++) {
//這就相當(dāng)于是創(chuàng)建了一個單元,然后向單元中填充數(shù)據(jù)
QStandardItem* newItem=new QStandardItem;
int ID = settings.value("ID").toInt();
int sendModeI = settings.value("SendMode").toInt();
if(settings.value("ExternFlag").toInt() == 0) {
externFlag = tr("Standard Frame");
idStr = settings.value("ID").toString().sprintf("0x%03X", ID);
} else {
externFlag = tr("Extend Frame");
idStr = settings.value("ID").toString().sprintf("0x%08X", ID);
}
switch(col) {
case CheckBox:
//CheckBox
//Qt::CheckStateRole 這代碼復(fù)選框角色
newItem->setData(Qt::Unchecked, Qt::CheckStateRole);
break;
case Id:
//ID
newItem->setData(idStr, Qt::DisplayRole);
newItem->setEditable(false);
break;
case Format:
//Format
if(settings.value("RemoteFlag").toInt() == 0) {
remoteFlag = tr("Data Frame");
} else {
remoteFlag = tr("Remote Frame");
}
if(((DevCan::instance().getDevType() == VCI_USBCANFD_II) ||
(DevCan::instance().getDevType() == VCI_USBCANFD_I)) &&
(DevCan::instance().getChannelType(channel) == CANFD_CH)) {
newItem->setData(remoteFlag, Qt::DisplayRole);
} else {
newItem->setData(remoteFlag, Qt::EditRole);
}
break;
case Type:
//Type
//Qt::EditRole 這代表可編輯角色
newItem->setData(externFlag, Qt::EditRole);
break;
case SendMode:
//SendMode
switch(sendModeI) {
case 0:
sendModeStr=tr("Normal Send");
break;
case 1:
sendModeStr=tr("Single Send");
break;
case 2:
sendModeStr=tr("Send & Receive");
break;
case 3:
sendModeStr=tr("Single Send&Rec");
break;
default:
break;
}
newItem->setData(sendModeStr, Qt::EditRole);
break;
case Length:
//Length
//Qt::DisplayRole 這個表示該列數(shù)據(jù)僅是展示,不可修改
newItem->setData(settings.value("DataLen").toString(), Qt::DisplayRole);
newItem->setEditable(false);
break;
case Data:
//Data(HEX)
newItem->setData(settings.value("Data").toString(), Qt::DisplayRole);
break;
case SendTimes:
//Send Times
newItem->setData(settings.value("Times").toString(), Qt::DisplayRole);
break;
case Interval:
//Interval(ms)
newItem->setData(settings.value("Interval").toString(), Qt::DisplayRole);
break;
case Count:
//Count
newItem->setData(0, Qt::DisplayRole);
newItem->setEditable(false);
break;
case CANType:
//CANType
if(settings.value("CANType").toInt() == 0) {
canTypeStr = "CAN";
} else {
canTypeStr = "CANFD";
}
newItem->setText(canTypeStr);
newItem->setData(canTypeStr, Qt::DisplayRole);
newItem->setEditable(false);
break;
case BRS:
//BRS
if(settings.value("BRS").toInt() == 0) {
brsStr = "Disable BRS";
} else {
brsStr = "Enable BRS";
}
// newItem->setText(brsStr);
newItem->setData(brsStr, Qt::DisplayRole);
newItem->setEditable(false);
break;
default:
break;
}
modelBottom->setItem(row, col, newItem);
}
idStr.clear();
externFlag.clear();
remoteFlag.clear();
sendModeStr.clear();
canTypeStr.clear();
brsStr.clear();
}
settings.endArray();
}
我們這里用到了復(fù)選框,我的項目中的主要是判斷哪一條數(shù)據(jù)是被選中了的,所以我需要判斷一下復(fù)選框的狀態(tài),被選中的數(shù)據(jù)會被發(fā)送到硬件設(shè)備上,代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-816442.html
void BottomTableView::sendMessage(int flag)
{
if(flag ==0) {
UlGlobalSet::instance().channel[channel].nStrategicType = TIMING;
} else if(flag ==1) {
UlGlobalSet::instance().channel[channel].nStrategicType = RECYCLE;
} else {
UlGlobalSet::instance().channel[channel].nStrategicType = ORDER;
}
QModelIndex index = ui->tableViewBottom->currentIndex();
int rows = index.model()->rowCount();
taskQueue tObjQ;
for(int i=0; i<rows; i++) {
QStandardItem* qs = modelBottom->item(i, 0);
QStandardItemModel* model = qs->model();
QModelIndex checkBoxIndex = model->index(i, CheckBox);
int isCheck = model->data(checkBoxIndex, Qt::CheckStateRole).toInt();
qDebug()<<"isCheck==="<<isCheck;
if(isCheck == Qt::Checked) {
taskObj tObj;
if(((DevCan::instance().getDevType() == VCI_USBCANFD_II) ||
(DevCan::instance().getDevType() == VCI_USBCANFD_I)) &&
(DevCan::instance().getChannelType(channel) == CANFD_CH)) {
if(analyseFDObj(tObj)) {
tObjQ.append(tObj);
}
} else {
if(analyseObj(tObj, i)) {
tObjQ.append(tObj);
}
}
}
}
}
代碼寫完之后就可以雙擊在你所設(shè)置的單元格中直接編輯了,展示一下頁面吧?。?!
初始頁面
下拉選擇修改
文本框編輯文章來源地址http://www.zghlxwxcb.cn/news/detail-816442.html
到了這里,關(guān)于【嵌入式——QT】QStyledItemDelegate用法詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!