- 思考:
QTableWidget
在某种程度上可以等价为QStandardItemModel
,同理,其他的功能也有类似的等价,但是以当前的QTableWidget
和QStandardItemModel
为例的话,两者都是用于实现建立表格的相关组件,只不过QStandardItemModel
使用更为灵活,可以自定义自己的模型
一 QFileSystemModel
,list,view,tree view应用于文件模型
- 知识点:下列案例是
QFileSystemModel
文件模型的应用
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileSystemModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_treeView_clicked(const QModelIndex &index);
private:
Ui::MainWindow *ui;
QFileSystemModel *model;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建模型
model = new QFileSystemModel;
//设置文件系统模型的根目录
//在这指定的目录下安装了一个文件系统监视器,这个目录下的文件信息的改变都会显示在这个模型里面
model->setRootPath(QDir::currentPath());
//关联模型和"视图"
ui->treeView->setModel(model);
ui->listView->setModel(model);
ui->tableView->setModel(model);
//list,tree,table是三种view,实现的功能是一样的,只是对当前文件系统的显示方式不一样
//使用信号槽,通知其他视图的即使变化,实现3种view同步变化
connect(ui->treeView,SIGNAL(clicked(QModelIndex)),ui->listView, SLOT(setRootIndex(QModelIndex)));
connect(ui->treeView,SIGNAL(clicked(QModelIndex)),ui->tableView, SLOT(setRootIndex(QModelIndex)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_treeView_clicked(const QModelIndex &index)
{
ui->labelFileName->setText(model->fileName(index));
float size = model->size(index) /1024; //?k
qDebug() << "size " << size;
if(size >1024){
ui->labelFileSize->setText(QString::asprintf("%.1f MB", size/1024.0)) ;
}else
{
ui->labelFileSize->setText(QString::asprintf("%f kB", size)) ;
}
ui->labelNodeType->setText(model->type(index));
ui->checkBox->setChecked(model->isDir(index));
ui->labelFilePath->setText(model->filePath(index));
}
二 QStringListModel
知识点:总结来说,模型的使用,包括以下几个步骤:
在.h文件中,定义模型指针
QStringListModel *model;
;在cpp文件的构造函数中,构建模型
model= new QStringListModel;
,构造数据/导入数据,
QStringList addrList = {"北京","上海","广州","深圳","贵州","杭州","深圳"}; model->setStringList(addrList);
模型和组件的关联
ui->listView->setModel(model);
- 数据添加完毕后,让鼠标选中新添加的数据新型显示
ui->listView->setCurrentIndex(index);
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStringListModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButtonEndAdd_clicked();
void on_pushButtonInsert_clicked();
void on_pushButtonDelete_clicked();
void on_pushButtonClear_clicked();
void on_pushButtonInit_4_clicked();
void on_pushButtonInit_3_clicked();
void on_pushButtonInit_2_clicked();
private:
Ui::MainWindow *ui;
QStringListModel *model;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建模型
model= new QStringListModel;
//构造数据/导入数据
QStringList addrList = {"北京","上海","广州","深圳","贵州","杭州","深圳"};
model->setStringList(addrList);
//关联
ui->listView->setModel(model);
ui->tableView->setModel(model);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButtonEndAdd_clicked()
{
//在尾部插入一行
model->insertRow(model->rowCount());
QModelIndex index = model->index(model->rowCount()-1,0); //获取最后一行第0列数据
//设置插入行的数据
model->setData(index,"新的城市");
//数据添加完毕后,让鼠标选中新添加的数据新型显示
ui->listView->setCurrentIndex(index);
}
void MainWindow::on_pushButtonInsert_clicked()
{
QModelIndex index = ui->listView->currentIndex();
model->insertRow(index.row());
model->setData(index,"插入新的城市");
ui->listView->setCurrentIndex(index);
}
void MainWindow::on_pushButtonDelete_clicked()
{
QModelIndex index = ui->listView->currentIndex();
model->removeRow(index.row());
}
void MainWindow::on_pushButtonClear_clicked()
{
model->removeRows(0,model->rowCount());
}
void MainWindow::on_pushButtonInit_4_clicked()
{
QStringList list = model->stringList();
ui->plainTextEdit->clear();
for(int i = 0; i < list.count(); i++){
ui->plainTextEdit->appendPlainText(list[i]);
}
}
void MainWindow::on_pushButtonInit_3_clicked()
{
ui->plainTextEdit->clear();
}
void MainWindow::on_pushButtonInit_2_clicked()
{
//构造数据/导入数据
QStringList addrList = {"北京","上海","广州","深圳","贵州","杭州","深圳"};
model->setStringList(addrList);
}
三 QStandardItemModel
- 问题:这种表格和table view之间的差别和联系是什么:是一种存储数据的模型,虽然展现的格式是表格,但是有自己的数据取出和存储方式,table view是一个组件工具
- 知识点:之前的自定义槽函数的命名模式是
on_actionBold_triggered
,on_信号_槽函数,这样做的前提是,信号是QT组件发出的信号,槽函数可以任意自定义,但是如果信号不是Qt组件发出的信号,而是自定义或者调用的类发出的信号,则最好不要这样命名,on_信号 即可,会导致找不到信号,虽然不会影响程序的正常运行。比如当前案例调用了一个类selectionModel = new QItemSelectionModel(model);
,这个类发出信号,点击类名QItemSelectionModel
查看相应的信号名,最终实现 根据单元格是否是粗体,要更新粗体图标的状态 的功能。 该案例就是用一个类发出信号,而非组件
// 添加信号槽 void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
connect(selectionModel, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this,SLOT(on_currentChanged(const QModelIndex &, const QModelIndex &)));
最终实现 根据单元格是否是粗体,要更新粗体图标的状态 的功能
//
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
if(current.isValid()){
auto item = model->itemFromIndex(current);
//根据当前选中单元格的字体是不是粗体来判断图标的变化,如果是粗体,图标状态是选中状态
//反之,不选中
ui->actionBold->setChecked(item->font().bold());
//在状态栏的标签中,显示所选中单元格是第几行第几列
labelinfo->setText(QString::asprintf("当前单元格:%d行,%d列",
current.row()+1,current.column()+1) +
" 单元格内容 " + item->text());
}
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_actionOpen_triggered();
void on_actionAdd_triggered();
void on_actionInsert_triggered();
void on_actionDelete_triggered();
void on_actionSee_triggered();
void on_actionSave_triggered();
void on_actionRight_triggered();
void on_actionLeft_triggered();
void on_actionMiddle_triggered();
void on_actionBold_triggered(bool checked);
void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
private:
Ui::MainWindow *ui;
QStandardItemModel *model;
QItemSelectionModel *selectionModel;
int collumCount; //列数
void initModel(QStringList content);
QLabel *labelinfo;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QTextStream>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
collumCount = 6;
model = new QStandardItemModel(2,collumCount, this);
selectionModel = new QItemSelectionModel(model);
ui->tableView->setModel(model);
ui->tableView->setSelectionModel(selectionModel); //对表数据选择模式,比如选中ctrl+鼠标可以多选
//配置table view的相关属性
//QAbstractItemView::ExtendedSelection:当前模式能实现以下的功能
//单击某选项,以前的选择会被取消
//同时按下ctrl,以前的选项和现在的选项都会保留
//同时按下shift,第一次选中的为左上角,当前选择为右下角的数据都会被选中
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
//选择单元格
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
// 添加信号槽 void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
connect(selectionModel, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this,SLOT(on_currentChanged(const QModelIndex &, const QModelIndex &)));
//手动添加标签到状态栏
labelinfo = new QLabel(this);
statusBar()->addWidget(labelinfo);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionOpen_triggered()
{
QString filiname = QFileDialog::getOpenFileName(this,"打开一个文件",QCoreApplication::applicationDirPath(), "文本数据文件(*txt);;所有文件(*.*)");
if(filiname.isEmpty()){
return;
}
QFile qfile(filiname);
//指定文件的打开方式,如果打不开,结束
if(!qfile.open(QIODevice::ReadOnly | QIODevice::Text)){
return;
}
QTextStream stream(&qfile);
QStringList fileContent;
while(!stream.atEnd()){
QString line = stream.readLine();
fileContent.append(line);
//把读到的内容放到右侧的文本编辑器
ui->plainTextEdit->appendPlainText(line);
}
qfile.close();
//将数据放置到数据模型里面去
initModel(fileContent);
}
void MainWindow::initModel(QStringList content)
{
//需要根据数据文本格式来进行切割
QString headline = content[0];
//QRegExp \s 自动匹配1个任意空白字符
//\s+ 自动匹配1个或者多个任意空白字符
// \\ 转移为'\'
QStringList headlist = headline.split(QRegExp("\\s+"),
QString::SkipEmptyParts); //跳过空格
model->setHorizontalHeaderLabels(headlist);
//读取数据
int rows = content.count();
for(int i =1 ;i < rows; i++){
QString line = content[i];
QStringList filedList = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
for(int j =0; j < collumCount-1; j++){
QStandardItem *item = new QStandardItem(filedList[j]);
model->setItem(i-1,j,item);
}
//取最后一列数据,将是打✔,否则维持原状
QStandardItem *item = new QStandardItem(headlist[collumCount-1]);
item->setCheckable(true); // 设置为可勾选
if(filedList[collumCount-1] == "否"){
item->setCheckState(Qt::Unchecked);
}else{
item->setCheckState(Qt::Checked);
}
model->setItem(i-1,collumCount-1,item);
}
}
void MainWindow::on_actionAdd_triggered()
{
QStringList initValue = {"无名","男","市场部","销售","50000","婚否"};
//将数据放入list中
QList <QStandardItem*> itemList;
for(int j =0; j < collumCount; j++){
QStandardItem *item = new QStandardItem(initValue[j]);
itemList.push_back(item);
}
itemList[collumCount-1]->setCheckable(true); // 设置为可勾选,最后一列数据是可选框的状态
model->insertRow(model->rowCount(), itemList); //默认在最后一行添加数据
//设置最后一行是被选中的状态
selectionModel->clearSelection();
QModelIndex index = model->index(model->rowCount() -1,0);
selectionModel->setCurrentIndex(index,QItemSelectionModel::Rows);
}
void MainWindow::on_actionInsert_triggered()
{
QStringList initValue = {"无名","男","市场部","销售","50000","婚否"};
QList <QStandardItem*> itemList;
for(int j =0; j < collumCount; j++){
QStandardItem *item = new QStandardItem(initValue[j]);
itemList.push_back(item);
}
itemList[collumCount-1]->setCheckable(true); // 设置为可勾选,最后一列数据是可选框的状态
QModelIndex index = selectionModel->currentIndex();
model->insertRow(index.row(), itemList);
//设置最后一行是被选中的状态
selectionModel->clearSelection();
selectionModel->setCurrentIndex(index,QItemSelectionModel::Rows);
}
void MainWindow::on_actionDelete_triggered()
{
QModelIndex index = selectionModel->currentIndex();
if(index.row() == model->rowCount()-1){
model->removeRow(index.row());
}else
{
model->removeRow(index.row());
selectionModel->setCurrentIndex(index,QItemSelectionModel::Select);
}
}
void MainWindow::on_actionSee_triggered()
{
//把左侧数据模型里面的数据,更新到右侧窗口
ui->plainTextEdit->clear();
//获取表头
QString str;
for(int i =0; i<model->columnCount(); i++)
{
QStandardItem *item = model->horizontalHeaderItem(i);
str += item->text() + "\t";
}
ui->plainTextEdit->appendPlainText(str); //会自动换行
//获取每一行数据
for(int i =1; i<model->rowCount(); i++)
{
str = " ";
for(int j =0; j<model->columnCount()-1; j++)
{
QStandardItem *item = model->item(i,j);
str += item->text() + "\t";
}
if(model->item(i,model->columnCount()-1)->checkState() == Qt::Checked){
str += "是";
}else{
str += "否";
}
ui->plainTextEdit->appendPlainText(str);
}
}
void MainWindow::on_actionSave_triggered()
{
//选择保存文件的储存路径
QString filename = QFileDialog::getSaveFileName(this,"保存文件",QCoreApplication::applicationDirPath());
if(filename.isEmpty()){
return;
}
QFile qfile(filename);
//指定文件的打开方式,如果打不开,结束,QIODevice::Truncate把文件截断为0,避免文件已经存在或者已经有数据了
if(!qfile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)){
qDebug() << "打不开";
return;
}
QTextStream stream(&qfile);
//读表头
QString str;
for(int i =0; i<model->columnCount(); i++)
{
QStandardItem *item = model->horizontalHeaderItem(i);
str += item->text() + "\t";
}
stream << str << "\n"; //写表头
//获取每一行数据
for(int i =1; i<model->rowCount(); i++)
{
str = " ";
for(int j =0; j<model->columnCount()-1; j++)
{
QStandardItem *item = model->item(i,j);
str += item->text() + "\t";
}
if(model->item(i,model->columnCount()-1)->checkState() == Qt::Checked){
str += "是";
}else{
str += "否";
}
stream << str << "\n"; //写数据
}
qfile.close();
}
void MainWindow::on_actionRight_triggered()
{
//对选择的单元格进行格式设置
//先判断是否有选中单元格
if(!selectionModel->hasSelection()){
return;
}
QModelIndexList indexlist = selectionModel->selectedIndexes();
for(int i = 0; i < indexlist.count();i++){
auto item = model->itemFromIndex(indexlist[i]);
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
}
void MainWindow::on_actionLeft_triggered()
{
if(!selectionModel->hasSelection()){
return;
}
QModelIndexList indexlist = selectionModel->selectedIndexes();
for(int i = 0; i < indexlist.count();i++){
auto item = model->itemFromIndex(indexlist[i]);
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
}
}
void MainWindow::on_actionMiddle_triggered()
{
if(!selectionModel->hasSelection()){
return;
}
QModelIndexList indexlist = selectionModel->selectedIndexes();
for(int i = 0; i < indexlist.count();i++){
auto item = model->itemFromIndex(indexlist[i]);
item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter);
}
}
void MainWindow::on_actionBold_triggered(bool checked)
{
if(!selectionModel->hasSelection()){
return;
}
QModelIndexList indexlist = selectionModel->selectedIndexes();
for(int i = 0; i < indexlist.count();i++){
auto item = model->itemFromIndex(indexlist[i]);
QFont font = item->font();
font.setBold(checked);
item->setFont(font);
}
}
//根据单元格是否是粗体,要更新粗体图标的状态
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
if(current.isValid()){
auto item = model->itemFromIndex(current);
//根据当前选中单元格的字体是不是粗体来判断图标的变化,如果是粗体,图标状态是选中状态
//反之,不选中
ui->actionBold->setChecked(item->font().bold());
//在状态栏的标签中,显示所选中单元格是第几行第几列
labelinfo->setText(QString::asprintf("当前单元格:%d行,%d列",
current.row()+1,current.column()+1) +
" 单元格内容 " + item->text());
}
}
四 自定义代理
- 上述三案例,没有设置表的可编辑模式,但是默认是可以编辑的,并且没有限制。但是如果不对输入数据进行限制,用户可能会输入不符合要求的数据,比如在性别后面输入数据。上一个案例可以编辑是因为使用了默认代理,所谓代理就是用于展示数据的一个媒介。因此优化上述案例,就可以通过自定义代理来实现
- 代理的两个作用,显示数据和编辑数据
4.1 自定义薪资代理
4.1.1 新建类文件
4.1.2 编辑类文件
- 在新建的类.h文件中,添加头文件
#include <QStyledItemDelegate>
,添加Q_OBJECT
- 让当前类继承于
QStyledItemDelegate
类,class QIntSlaryDelegate: public QStyledItemDelegate
- 构造函数修改为有参构造
QIntSlaryDelegate(QObject *parent = 0);
- 点击
QStyledItemDelegate
,转到类定义,将以下四个函数直接复制到新建类里面,createEditor
作用是创建组件,setEditorData
:将模型的数据给代理,setModelData
:将代理里面的数据给到模型,updateEditorGeometry
:设置显示格式 - 设置组件的时候,根据数据需求来选择组件,比如当前的显示的数据是整型数据,要获取能够上下拨动的按钮的功能,对应的组件就是
QSpinBox
#ifndef QINTSLARYDELEGATE_H
#define QINTSLARYDELEGATE_H
#include <QStyledItemDelegate>
class QIntSlaryDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
QIntSlaryDelegate(QObject *parent = 0);
// editing
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;
};
#endif // QINTSLARYDELEGATE_H
#include "qintslarydelegate.h"
#include <QSpinBox>
#include <QDebug>
QIntSlaryDelegate::QIntSlaryDelegate(QObject *parent):QStyledItemDelegate(parent)
{
}
//创建代理组件的时候,调用这个虚函数
QWidget *QIntSlaryDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
//QSpinBox只能输入证整数,右侧有上下两个可调箭头的框
QSpinBox *eidtor = new QSpinBox(parent);
eidtor->setMinimum(2000);
eidtor->setMaximum(100000);
eidtor->setSingleStep(100);
return eidtor;
}
//将模型的数据给代理
void QIntSlaryDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
//从数据模型获取数据
int value = index.model()->data(index).toInt();
QSpinBox *spinbox = static_cast<QSpinBox*>(editor); //获取代理组件,并转换成相应的组件类型
spinbox->setValue(value);
}
//将代理里面的数(可能已经修改)据,给到模型
void QIntSlaryDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QSpinBox *spinbox = static_cast<QSpinBox*>(editor);
spinbox->interpretText(); //解释数据, 输入的都是文本,这要要的是整数
int value = spinbox->value();
model->setData(index,value);
}
void QIntSlaryDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
editor->setGeometry(option.rect); //设置代理的大小就是原本的模型数据的小大
}
4.1.3 编辑mainwindow对应文件
- 在
mainwindow.h
文件中,包含新建类的头文件#include "qintslarydelegate.h"
, - 在private下,定义
QIntSlaryDelegate intSalaryDelegate;
- 在
mainwindow.cpp
文件中,构造函数里面指定代理,ui->tableView->setItemDelegateForColumn(4,&intSalaryDelegate);
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QLabel>
#include "qintslarydelegate.h"
#include "qfloatdelegate.h"
#include "qcomboxdelegate.h"
#include "qdatedelegate.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_actionOpen_triggered();
void on_actionAdd_triggered();
void on_actionInsert_triggered();
void on_actionDelete_triggered();
void on_actionSee_triggered();
void on_actionSave_triggered();
void on_actionRight_triggered();
void on_actionLeft_triggered();
void on_actionMiddle_triggered();
void on_actionBold_triggered(bool checked);
void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
private:
Ui::MainWindow *ui;
QStandardItemModel *model;
QItemSelectionModel *selectionModel;
int collumCount; //列数
void initModel(QStringList content);
QLabel *labelinfo;
QIntSlaryDelegate intSalaryDelegate;
QFloatDelegate floatDelegate;
QComboxDelegate jobDelagete;
QComboxDelegate genderDelegate;
QDateDelegate dataDelegate;
};
#endif // MAINWINDOW_H
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
。。。。。 。。。。。 。。。。。
//指定代理
ui->tableView->setItemDelegateForColumn(4,&intSalaryDelegate);
ui->tableView->setItemDelegateForColumn(5,&floatDelegate);
jobDelagete.setItemList(QStringList{"软件工程师","硬件工程师","经理","助理"});
ui->tableView->setItemDelegateForColumn(3,&jobDelagete);
genderDelegate.setItemList(QStringList{"男","女"});
ui->tableView->setItemDelegateForColumn(1,&genderDelegate);
ui->tableView->setItemDelegateForColumn(2,&dataDelegate);
}
4.2 自定义绩效系数代理
- 和4.1的区别就只在于组件类型不同,用的组件是
QDoubleSpinBox
类文件的.cpp文件
#include "qfloatdelegate.h"
#include <QDoubleSpinBox>
QFloatDelegate::QFloatDelegate(QObject *parent):QStyledItemDelegate(parent)
{ }
QFloatDelegate::QFloatDelegate(){
}
QWidget *QFloatDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setMaximum(5);
editor->setSingleStep(0.1);
return editor;
}
void QFloatDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
float value = index.model()->data(index).toFloat();
QDoubleSpinBox *spinbox = static_cast<QDoubleSpinBox*>(editor);
spinbox->setValue(value);
}
void QFloatDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QDoubleSpinBox *spinbox = static_cast<QDoubleSpinBox*>(editor);
spinbox->interpretText();
float value = spinbox->value();
QString str = QString::asprintf("%.1f", value);
model->setData(index,str);
}
void QFloatDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
editor->setGeometry(option.rect); //设置代理的大小就是原本的模型数据的小大
}
4.3 自定义多选框岗位和性别代理,一个代理对应两个变量
- 知识点:当前案例和上述有所不同,一个代理对应了两个变量,
createEditor
函数中的定义有所不同,使用的是addItems
而不是addItem
,添加的是QStringList
,
QWidget *QComboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItems(itemList);
return editor;
}
并设计了一个类的对外的接口,以便在调用的时候来完成itemList
的值的设置,因此在mianwindow.cpp
构造函数中指定代理前,需要调用该接口来指定QStringList
里面的值
jobDelagete.setItemList(QStringList{"软件工程师","硬件工程师","经理","助理"});
ui->tableView->setItemDelegateForColumn(3,&jobDelagete);
genderDelegate.setItemList(QStringList{"男","女"});
ui->tableView->setItemDelegateForColumn(1,&genderDelegate);
#ifndef QCOMBOXDELEGATE_H
#define QCOMBOXDELEGATE_H
#include <QStyledItemDelegate>
class QComboxDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
QComboxDelegate(QObject *parent = 0);
// editing
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;
void setItemList(const QStringList &list);
private:
QStringList itemList;
};
#endif // QCOMBOXDELEGATE_H
#include "qcomboxdelegate.h"
#include <QComboBox>
QComboxDelegate::QComboxDelegate(QObject *parent):QStyledItemDelegate(parent)
{}
QWidget *QComboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItems(itemList);
return editor;
}
//从数据模型取数据,给代理组件
void QComboxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString value = index.model()->data(index).toString();
QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->setCurrentText(value);
}
void QComboxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QString str = comboBox->currentText();
model->setData(index,str);
}
void QComboxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
editor->setGeometry(option.rect); //设置代理的大小就是原本的模型数据的小大
}
void QComboxDelegate::setItemList(const QStringList &list)
{
itemList = list;
}