QT (四)模型/视图 QFileSystemModel,QStringListModel,QStandardItemModel

news2025/3/31 22:51:02
  • 思考: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 &current, 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 &current, 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 &current, 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 &current, 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 &current, 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 &current, 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2300082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

. Unable to find a @SpringBootConfiguration(默认软件包中的 Spring Boot 应用程序)

解决&#xff1a; 新建一个包即可 问题&#xff1a; 默认软件包中的 Spring Boot 应用程序。 原因&#xff1a; 默认包的定义 &#xff1a; 如果一个 Java 类没有使用 package 声明包名&#xff0c;则该类会被放置在默认包中。Spring Boot 遵循 Java 的包管理约定&#xff…

FRRouting配置与OSPF介绍,配置,命令,bfd算法:

文章目录 1、frrouting的配置&#xff1a;2、ospf2.1、检测和维护邻居关系2.2、ospfDR和BDR2.3、odpf邻居表2.4、ospf常用命令2.5、bfd配置 1、frrouting的配置&#xff1a; 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 预编译…

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:机器学习模型的巅峰对决

我的个人主页 我的专栏&#xff1a;人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞&#x1f44d;收藏❤ 一、引言 在机器学习的广袤天地中&#xff0c;大型语言模型&#xff08;LLM&#xff09;无疑是最…

内容中台重构企业内容管理流程驱动智能协作升级

内容概要 内容中台作为企业数字化转型的核心基础设施&#xff0c;通过技术架构革新与功能模块整合&#xff0c;重构了传统内容管理流程的底层逻辑。其核心价值在于构建动态化、智能化的内容生产与流转体系&#xff0c;将分散的创作、存储、审核及分发环节纳入统一平台管理。基…

STM32 Flash详解教程文章

目录 Flash基本概念理解 Flash编程接口FPEC Flash擦除/写入流程图 Flash选项字节基本概念理解 Flash电子签名 函数读取地址下存放的数据 Flash的数据处理限制部分 编写不易&#xff0c;请勿搬运&#xff0c;感谢理解&#xff01;&#xff01;&#xff01; Flash基本概念…

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器刷机教程&#xff08;Pandavan&#xff09; 一、前言 小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而&#xff0c;原厂固件的功能相对有限&#xff0c;难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能&#xff0c;还能通过第三方固…

红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问

针对 Kubernetes API 扩展与未授权访问 的详细攻击视角分析&#xff0c;聚焦 Custom Resource Definitions (CRD) 和 Aggregated API Servers 的潜在攻击面及利用方法&#xff1a; ​ 攻击链示例 1. 攻击者通过 ServiceAccount Token 访问集群 → 2. 枚举 CRD 发现数据库配…

11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行)

11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行) 文章目录 11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行)2. 最后&#xff1a; 建 Module - docker_boot 编辑 pom <?xml version"1.0&…

计算机视觉:卷积神经网络(CNN)基本概念(二)

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络 接上一篇《计算机视觉&am…

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…

dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型

要将 dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型. 申请阿里云百练的KEY 添加模型 测试模型

应用分层、三层架构和MVC架构

前言 在前面中&#xff0c;我们已经学习了Spring MVC 的一些基础操作&#xff0c;那么后面就用一些简单的案例来巩固一下。 在开始学习做案例之前&#xff0c;我们先来了解一下在软件开发中常见的设计模式和架构。 应用分层 含义 应用分层是一种软件开发设计思想&#xff0…

Apache Struts2 - 任意文件上传漏洞 - CVE-2024-53677

0x01&#xff1a;漏洞简介 Apache Struts 是美国 Apache 基金会的一个开源项目&#xff0c;是一套用于创建企业级 Java Web 应用的开源 MVC 框架&#xff08;将软件分为模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&a…

传统混合专家模型MoE架构详解以及python示例(DeepSeek-V3之基础)

我们已经了解到DeepSeek-V3的框架结构基于三大核心技术构建:多头潜在注意力(MLA)、DeepSeekMoE架构和多token预测(MTP)。而DeepSeekMoE架构的底层模型采用了混合专家模型(Mixture of Experts,MoE)架构。所以我们先了解一下传统混合专家模型MoE架构。 一、传统混合专家模…

安全筑基,智能赋能:BeeWorks IM引领企业协同新纪元

在数字经济高速发展的今天&#xff0c;企业通讯系统已从单纯的信息传递工具演变为支撑业务创新的核心平台。传统通讯工具在安全性、智能化、协同性等方面的不足&#xff0c;严重制约着企业的数字化转型进程。BeeWorks IM系统以其创新的技术架构和智能化功能&#xff0c;正在重新…

solidworks零件的绘制学习

1、拉伸凸台拉伸切除可以在一个零件中打孔&#xff0c;如下图&#xff1a; 2、旋转凸台配合旋转切除&#xff1b; 3、薄壁特征&#xff1a;在拉伸凸台&#xff0c;旋转凸台中都有&#xff1b;在一个面中画完草图&#xff0c;然后选择拉伸凸台或旋转凸台&#xff0c;里面就会出…

llama.cpp部署 DeepSeek-R1 模型

一、llama.cpp 介绍 使用纯 C/C推理 Meta 的LLaMA模型&#xff08;及其他模型&#xff09;。主要目标llama.cpp是在各种硬件&#xff08;本地和云端&#xff09;上以最少的设置和最先进的性能实现 LLM 推理。纯 C/C 实现&#xff0c;无任何依赖项Apple 芯片是一流的——通过 A…

Spring源码分析のBean创建流程(上)

文章目录 前言一、preInstantiateSingletons1.1、getMergedLocalBeanDefinition1.2、isFactoryBean 二、getBean 前言 原生Spring在refresh方法中&#xff0c;会在finishBeanFactoryInitialization&#xff1a;preInstantiateSingletons方法中直接创建所有非懒加载的单例Bean。…