当前位置: 首页 > article >正文

MV结构下设置Qt表格的代理

目录

预备知识

模型

关联

刷新

示例

代理

模型

界面

结果

完整资料见:


所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客,如设置QTableView的内容自动换行(2)_qstandarditem 文本换行显示-CSDN博客

如何截获QTableView的鼠标事件?_qtableview里面捕获鼠标移动事件-CSDN博客 

QAbstractItemModel数据更新-CSDN博客 

Qt如何正确的显示、修改表格(QTableView)的内容_qt tableview修改表格内容-CSDN博客 

我已经花了很多笔墨描述Qt表格的软件设计方法。在本篇文章中,我将介绍如何编辑表格--表格代理。

预备知识

模型

模型用来存储表格数据。这个类通常派生自QAbstractTableModel。这个派生类的通常由如下几个部分组成:

成员变量:

m_data                                    m_data通常是一个list,vector或者map等常见的数据结构。

                                                用来存储数据。                   

以下为虚函数:

columnCount                          列数

rowCount                                行数

data                                        表格显示的内容

flags                                        flags决定了各个单元格可否被编辑。假如不需要编辑表格,

                                                也可以不重写此虚函数

headerData                             headerData返回值决定了各行/列标题名称

setData                                   setData决定了编辑单元格以后,编辑结果如何影响m_data。

                                                假如不需要编辑表格,也可以不重写此虚函数

关联

通过QTableView::setModel()建立与模型的关联

刷新

当m_data发生变化时,或者界面需要刷新时,刷新动作由dataChanged信号触发。很多人奇怪,怎么没看到对应dataChanged的槽函数?Qt内部已经将dataChanged与对应的槽函数做了关联,开发者不必操心,只要发出信号即可。

示例

代理

专门建立一个代理类

#include "EdtDelegate.h"


EdtDelegate::EdtDelegate(int iMin, int iMax, QObject *parent)
    : QStyledItemDelegate(parent)
{
    m_pIntVld = new QIntValidator(iMin, iMax, this);
}

EdtDelegate::~EdtDelegate()
{

}

QWidget *EdtDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex &/* index */) const
{
    QLineEdit *editor = new QLineEdit(parent);
    editor->setValidator(m_pIntVld);

    return editor;
}

void EdtDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    QString qstrTxt = index.model()->data(index, Qt::DisplayRole).toString();

    QLineEdit *Edt = static_cast<QLineEdit*>(editor);
    Edt->setText(qstrTxt);
}

void EdtDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QLineEdit *edt = static_cast<QLineEdit*>(editor);
    auto qstrTxt = edt->text();

    model->setData(index, qstrTxt, Qt::EditRole);
}

void EdtDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

#include "ComboDelegate.h"

#include <QComboBox>

  ComboDelegate::ComboDelegate(QStringList qstrlst, QObject *parent)
      : QStyledItemDelegate(parent), m_qstrlst(qstrlst)
  {
  }

  QWidget *ComboDelegate::createEditor(QWidget *parent,
      const QStyleOptionViewItem &/* option */,
      const QModelIndex &/* index */) const
  {
      QComboBox *editor = new QComboBox(parent);
      editor->addItems(m_qstrlst);

      return editor;
  }

  void ComboDelegate::setEditorData(QWidget *editor,
                                      const QModelIndex &index) const
  {
      QString qstrTxt = index.model()->data(index, Qt::DisplayRole).toString();

      QComboBox *cmbBox = static_cast<QComboBox*>(editor);
      cmbBox->setCurrentText(qstrTxt);
  }

  void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                     const QModelIndex &index) const
  {
      QComboBox *cmbBox = static_cast<QComboBox*>(editor);
      auto qstrTxt = cmbBox->currentText();

      model->setData(index, qstrTxt, Qt::EditRole);
  }

  void ComboDelegate::updateEditorGeometry(QWidget *editor,
      const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
  {
      editor->setGeometry(option.rect);
  }

这里有人会问,createEditor里面有new的动作,为什么没看到释放?createEditor返回一个指针。Qt内部有一套机制,在编辑结束后,自动释放该指针。

模型

#include "Model.h"


//Model
Model::Model(int iTotalCol, QStringList qstrlstHeader, QList<int> lstNonEditableCols,
             QObject *parent) : QAbstractTableModel(parent),
    m_lstNonEditableCols(lstNonEditableCols),
    m_iTotalCol(iTotalCol), m_qstrlstHeader(qstrlstHeader)
{

}

int Model::rowCount(const QModelIndex &) const
{
    return m_data.size();
}

int Model::columnCount(const QModelIndex &) const
{
    return m_iTotalCol;
}

QVariant Model::data(const QModelIndex &index, int role) const
{
    int i = index.row(), j = index.column();
    if ((i >= 0) && (i < m_data.size()))
    {
        if(m_data.at(i).size() > j)
        {
            if(role == Qt::DisplayRole)
            {
                //m_data的类型是QList<QStringList>,每一个QStringList对应表格里一行数据
                //m_data.at(i).at(j)对应的就是第i行,第j列的数据
                return m_data.at(i).at(j);
            }
            else if(role == Qt::TextAlignmentRole)
                return Qt::AlignCenter;
            else
            {

            }
        }
        else
        {
            return QString("");
        }
    }
    else
    {

    }

    return QVariant();
}

QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role == Qt::DisplayRole)
    {
        if(orientation == Qt::Horizontal)//横向排列的标题栏,也就是各个列的标题
        {
            if(m_qstrlstHeader.size() > section)
                return m_qstrlstHeader.at(section);
            else
            {
                return QString("");
            }
        }
        else
        {
            //纵向排列的标题栏,也就是各个行的标题
            return QString("");
        }
    }
    else if(role == Qt::TextAlignmentRole)
    {
        //文字对齐方式设置为居中对齐
        return Qt::AlignCenter;
    }
    else
    {

    }

    return QAbstractTableModel::headerData(section, orientation, role);
}

void Model::vSetData(QList<QStringList> & lstData)
{
    m_data.clear();
    m_data.append(lstData);
    //发出dataChanged信号,界面上才更新表格内容
    emit dataChanged(createIndex(0,0), createIndex(0, columnCount()-1));
}


Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
    if(m_lstNonEditableCols.contains(index.column()))
        //假如index对应的列是不可编辑的列
        return QAbstractTableModel::flags(index);
    else
        //假如index对应的列是可编辑的列,就给它添加ItemIsEditable属性
        return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}

bool Model::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(role == Qt::EditRole)
    {
        //编辑单元格之后,用编辑结果更新对应的m_data
        int row = index.row(), col = index.column();
        QStringList qstrlst = m_data.at(row);
        qstrlst.replace(col, value.toString());
        m_data.replace(row, qstrlst);
    }

    return true;
}

界面

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pModel = new Model(4, {"1", "2", "3", "4"}, {0,1});
    ui->tableView->setModel(m_pModel);
    //setEditTriggers(QTableView::DoubleClicked);注明触发编辑单元格的方式是鼠标双击
    ui->tableView->setEditTriggers(QTableView::DoubleClicked);
    QList<QStringList> lstqstrlst;
    lstqstrlst<<QStringList{"a", "b", "c", "d"};
    //向表格中注入数据
    m_pModel->vSetData(lstqstrlst);

    m_scpCmbDelg.reset(new ComboDelegate({"a","b","c"}, this));
    //表格第2列采用combobox代理(其实是第3列,因为从0开始)
    ui->tableView->setItemDelegateForColumn(2, m_scpCmbDelg.data());

    m_scpEdtDelg.reset(new EdtDelegate(0,10, this));
    //表格第3列采用lineedit代理
    ui->tableView->setItemDelegateForColumn(3, m_scpEdtDelg.data());
}

MainWindow::~MainWindow()
{
    delete ui;
}

结果

双击第一列、第二列,无法编辑单元格。但是双击第三列,可以编辑combobox;双击第四列,可以编辑lineedit:

qt代理,访问csdn金色熊族,获取完整信息

完整资料见:

【免费】介绍如何给Qt表格添加代理资源-CSDN文库


http://www.kler.cn/a/524551.html

相关文章:

  • PySide(PyQT)进行SQLite数据库编辑和前端展示的基本操作
  • 51单片机开发:独立键盘实验
  • 再见了流氓软件~~
  • 27.useFetch
  • git困扰的问题
  • Winform如何取消叉号,减号和放大(两种)
  • EXCEL教程:如何打开Excel隐藏部分?
  • JavaScript - Web APIs(上)
  • 基于Arcsoft的人脸识别
  • doris:异常数据处理
  • DeepSeek部署教程(基于Ollama)
  • 具身智能研究报告
  • 展示统计信息收集情况
  • redis缓存和springboot缓存包冲突怎么办
  • 再见了流氓软件~~
  • 什么是AGI
  • PyTorch中的movedim、transpose与permute
  • [特殊字符] x-cmd pkg | fzf (1) - 强大的模糊搜索工具,一条命令颠覆你的命令行交互体验
  • Autogen_core 测试代码:test_cache_store.py
  • 003 mapper代理开发方式-注解方式
  • 64位的谷歌浏览器Chrome/Google Chrome
  • Maven项目JUnit测试的远程调试技巧
  • 深度学习中常用的评价指标方法
  • 剑指 Offer II 002. 二进制加法
  • 探索高效图像识别:基于OpenCV的形状匹配利器
  • git中有关old mode 100644、new mode 10075的问题解决小结