QT (四)模型/视图 QFileSystemModel,QStringListModel,QStandardItemModel
- 思考:
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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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; //?kqDebug() << "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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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);// editingQWidget *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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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);// editingQWidget *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;
}相关文章:
QT (四)模型/视图 QFileSystemModel,QStringListModel,QStandardItemModel
思考:QTableWidget 在某种程度上可以等价为QStandardItemModel,同理,其他的功能也有类似的等价,但是以当前的QTableWidget 和QStandardItemModel为例的话,两者都是用于实现建立表格的相关组件,只不过QStand…...
BSD实现:单播
分用单播数据报 如果程序执行到这里,说明程序并没有执行多播操作,那么大概率是单播。 维护缓存指针 udp_last_inpcb是上一次接收数据报的端口的控制块指针,维护该指针的依据是许多程序往往具有时间局部性,也就是:经…...
. Unable to find a @SpringBootConfiguration(默认软件包中的 Spring Boot 应用程序)
解决: 新建一个包即可 问题: 默认软件包中的 Spring Boot 应用程序。 原因: 默认包的定义 : 如果一个 Java 类没有使用 package 声明包名,则该类会被放置在默认包中。Spring Boot 遵循 Java 的包管理约定ÿ…...
【前端知识】浏览器兼容方案polyfill
浏览器兼容方案polyfill 什么是 Polyfill?Polyfill 的作用Polyfill 的工作原理1. **特性检测**2. **加载 Polyfill**3. **模拟实现** Polyfill 的常见场景Polyfill 的使用方式Polyfill 的优缺点优点缺点 常见的 Polyfill 库总结 什么是 Polyfill? Polyf…...
互信息的定义与公式
互信息 定义公式 从条件熵中我们知道,当获取的信息和要研究的食物”有关系时“,这些信息才能帮助我们消除不确定性。如何衡量获取信息和要研究事物“有关系”呢?比如常识告诉我们,一个随机事件“今天深圳下雨”和另一个随机事件“…...
(算法基础——树)——python树结构使用指南
1. 树的定义与实现 树是一种非线性数据结构,常用于解决层次化数据问题(如路径搜索、二叉树遍历等)。以下是树的两种常见实现方式: (1) 类(Class)实现 class TreeNode:def __init__(self, val0, leftNone…...
【小白学AI系列】NLP 核心知识点(七)Embedding概念介绍
Embedding(嵌入) 是自然语言处理(NLP)中非常重要的概念。简单来说,embedding 是一种将离散的、稀疏的、不可直接计算的对象(比如词、字符或句子)转换为 密集的、连续的向量表示 的技术。 这个向…...
Android adb测试常用命令大全
目录 一、查看最上层成activity名字: 二、查看Activity的任务栈: 三、获取安装包信息 四、性能相关 1、显示CPU信息 : 2、查看CPU使用信息 3、内存信息(meminfo package_name or pid 使用程序的包名或者进程id显示内存信息) 4、电量信…...
FRRouting配置与OSPF介绍,配置,命令,bfd算法:
文章目录 1、frrouting的配置:2、ospf2.1、检测和维护邻居关系2.2、ospfDR和BDR2.3、odpf邻居表2.4、ospf常用命令2.5、bfd配置 1、frrouting的配置: sudo service zebra start sudo service ospfd start telnet localhost 2604 en configure termina…...
【MyBatis】预编译SQL与即时SQL
目录 1. 以基本类型参数为例测试#{ }与${ }传递参数的区别 1.1 参数为Integer类型 1.2 参数为String类型 2. 使用#{ }传参存在的问题 2.1 参数为排序方式 2.2 模糊查询 3. 使用${ }传参存在的问题 3.1 SQL注入 3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题 3.3 预编译…...
prometheus、grafana、windows、node exporter 安装包
开发过程中应用到的安装包软件: prometheus-2.20.0.windows-amd64.tar.gz windows_exporter-0.13.0-amd64.exe grafanawindows-x64.zip influxdb-1.7.0_windows_amd64.zip 我用夸克网盘分享了「prometheus、grafana、windows、node exporter 安装包」ÿ…...
Python数据可视化 - Matplotlib教程
文章目录 前言一、Matplotlib简介及安装1. Matplotlib简介2. 安装Matplotlib 二、Matplotlib Pyplot1. Pyplot介绍2. Pyplot中方法介绍2.1 创建和管理图形2.2 绘制图形2.3 设置图形属性2.4 保存和展示 三、Matplotlib绘图标记1. 介绍2. 基本用法3. 标记大小与颜色4. 标记样式列…...
DeepSeek R1 与 OpenAI O1:机器学习模型的巅峰对决
我的个人主页 我的专栏:人工智能领域、java-数据结构、Javase、C语言,希望能帮助到大家!!!点赞👍收藏❤ 一、引言 在机器学习的广袤天地中,大型语言模型(LLM)无疑是最…...
内容中台重构企业内容管理流程驱动智能协作升级
内容概要 内容中台作为企业数字化转型的核心基础设施,通过技术架构革新与功能模块整合,重构了传统内容管理流程的底层逻辑。其核心价值在于构建动态化、智能化的内容生产与流转体系,将分散的创作、存储、审核及分发环节纳入统一平台管理。基…...
STM32 Flash详解教程文章
目录 Flash基本概念理解 Flash编程接口FPEC Flash擦除/写入流程图 Flash选项字节基本概念理解 Flash电子签名 函数读取地址下存放的数据 Flash的数据处理限制部分 编写不易,请勿搬运,感谢理解!!! Flash基本概念…...
小米 R3G 路由器刷机教程(Pandavan)
小米 R3G 路由器刷机教程(Pandavan) 一、前言 小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而,原厂固件的功能相对有限,难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能,还能通过第三方固…...
红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问
针对 Kubernetes API 扩展与未授权访问 的详细攻击视角分析,聚焦 Custom Resource Definitions (CRD) 和 Aggregated API Servers 的潜在攻击面及利用方法: 攻击链示例 1. 攻击者通过 ServiceAccount Token 访问集群 → 2. 枚举 CRD 发现数据库配…...
11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行)
11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行) 文章目录 11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行)2. 最后: 建 Module - docker_boot 编辑 pom <?xml version"1.0&…...
mysql和minio
在现代应用架构中,Word 文档、PPT 等文件通常存储在对象存储服务(如 MinIO)中,而不是直接存储在关系型数据库(如 MySQL)中。以下是具体的分工和原因: 为什么选择对象存储(如 MinIO&a…...
计算机视觉:卷积神经网络(CNN)基本概念(二)
第一章:计算机视觉中图像的基础认知 第二章:计算机视觉:卷积神经网络(CNN)基本概念(一) 第三章:计算机视觉:卷积神经网络(CNN)基本概念(二) 第四章:搭建一个经典的LeNet5神经网络 接上一篇《计算机视觉&am…...
【数据结构-红黑树】
文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树(Red-Black Tree)是一种自平衡的二叉查找树(Binary Search Tree, BST)&…...
dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型
要将 dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型. 申请阿里云百练的KEY 添加模型 测试模型...
手机ROM是什么
本篇将以我自己的手机——小米13为例 手机 ROM 详解 在手机领域,ROM(Read-Only Memory) 通常指的是 手机的操作系统和固件,包括 Android 设备的 系统镜像(system.img)、引导程序(boot.img&…...
应用分层、三层架构和MVC架构
前言 在前面中,我们已经学习了Spring MVC 的一些基础操作,那么后面就用一些简单的案例来巩固一下。 在开始学习做案例之前,我们先来了解一下在软件开发中常见的设计模式和架构。 应用分层 含义 应用分层是一种软件开发设计思想࿰…...
Apache Struts2 - 任意文件上传漏洞 - CVE-2024-53677
0x01:漏洞简介 Apache Struts 是美国 Apache 基金会的一个开源项目,是一套用于创建企业级 Java Web 应用的开源 MVC 框架(将软件分为模型(Model)、视图(View)和控制器(Controller&a…...
传统混合专家模型MoE架构详解以及python示例(DeepSeek-V3之基础)
我们已经了解到DeepSeek-V3的框架结构基于三大核心技术构建:多头潜在注意力(MLA)、DeepSeekMoE架构和多token预测(MTP)。而DeepSeekMoE架构的底层模型采用了混合专家模型(Mixture of Experts,MoE)架构。所以我们先了解一下传统混合专家模型MoE架构。 一、传统混合专家模…...
Tomcat如何处理Http请求
Tomcat处理HTTP请求的流程是一个复杂但有序的过程,涉及多个组件的协同工作。以下是对Tomcat处理HTTP请求流程的详细讲解: 一、接收请求 监听端口:Tomcat通过配置的Connector组件监听特定的端口(默认是8080)ÿ…...
安全筑基,智能赋能:BeeWorks IM引领企业协同新纪元
在数字经济高速发展的今天,企业通讯系统已从单纯的信息传递工具演变为支撑业务创新的核心平台。传统通讯工具在安全性、智能化、协同性等方面的不足,严重制约着企业的数字化转型进程。BeeWorks IM系统以其创新的技术架构和智能化功能,正在重新…...
AlmaLinux使用Ansible自动部署k8s集群
一、环境准备 节点规划(最低要求) 1台Master节点(4核/8GB内存)2台Worker节点(2核/4GB内存)1台Ansible控制机(可复用Master节点) 系统配置 # 所有节点执行 sudo hostnamectl set-hos…...
solidworks零件的绘制学习
1、拉伸凸台拉伸切除可以在一个零件中打孔,如下图: 2、旋转凸台配合旋转切除; 3、薄壁特征:在拉伸凸台,旋转凸台中都有;在一个面中画完草图,然后选择拉伸凸台或旋转凸台,里面就会出…...
