基于QTableView中的MVD代理添加总结

目录

1、Qt中MVD说明

1.1 View

1.2 Delegate

1.3 Model/View的基本原理

2、代码是现实示例

2.1 设置样式文件

2.2 set base attribute

 2.3 设置model

2.4 设置表头

2.5 设置数据     

2.6 添加代理控件

2.6.1 添加 QSpinBox 代理 

2.6.2 添加 QComboBox 代理

2.6.3 添加 QPushButton 代理

2.6.4 添加 CheckBox 代理 

2.6.5 添加 Pixmap 代理

2.6.6 添加 LineEdit 代理

2.6.7 添加 ReadOnly 代理

2.6.8 添加 Text 代理 

2.6.9 添加 QProcessBar 代理

2.6.10 添加 DateEdit 代理

2.6.11 添加 添加自定义窗口 代理 

2.6.12 添加 DoubleProcessBar 代理

2.7 获取某一单元格数据 



开发过程中进程使用MVD模型,添加各种代理控件,本文在此基础上整理一些数据模型代理,包括:QPushbutton、QLineEdit、QPixmap、QChecledBox、QComboBox、QSpinBox、QProcessBar、只读列、自定义窗口等共13种代理方式,如图所示:

在此之前,先来说明一下对MVD做一简单说明:

1、Qt中MVD说明

        在传统的MVC模型中,view用于向用户展示model数据。但是,Qt提供的并不是MVC架构,而是一个model/view的设计(也就是说,没有包含一个完整而独立的组件用于管理用户的交互)。一般来说,view仅仅是作用于model数据的展示和用户输入的处理,而不应该去做其他的工作。在这种结构中,为了获得对用户输入控制的灵活性,就将这种交互工作交给了delegate完成(也就是“委托”)。简单来说,就是view将用户输入委托给delegate处理,而不自己去处理。这些组件提供一种输入能力,并且能够在某些view中提供这种交互情形下的渲染,比如在table中双击某单元格进行编辑等。

1.1 View

        QListView、QTreeView、QTableView

1.2 Delegate

        Delegate可以用于渲染内容,这是通过paint() 和sizeHint()函数来完成的。但是对于一些简单的基于组件的delegate,可以通过继承QItemdelegate或者QStyledItemDelegate 来实现,而不需要重写虚函数。

Qt提供的标准组件中使用QItemDelegate提供编辑功能的支持。这种默认的实现被用在QListView,QTableView和QTreeView中。View实用的delegate可以通过itemDelegate()函数获得,其中,setItemDelegate()函数则可以为一个标准组件设置自定义的delegate.

在Qt4.4之后提供QItemDelegate/QStyledItemDelegate ,可以把控件设置成只读、表格的某一列制定自己需要的控件。默认的委托是QStyledItemDelegate。这两个类可以被相互替代,给view组件提供绘制和编辑功能。主要区别在于,QStyledItemDelegate使用当前的风格(style)去绘制组件,所以当需要设置 qt style sheet时建议使用QStyleItemDelegaet作为父类。使用这两个类的代码是一样的,除了需要使用style进行绘制的部分。

注意:绘制和向视图提供编辑器的方式,但使用起来感觉区别不是很大,之前使用过代理第一时间想到的是重写代理,实现虚函数,在虚函数中创建自己想要的控件并返回就OK了,但是运行程序时发现并没有默认显示出来,只有在编辑的时候显示(也就是双击的时候),这种方式用在输入限制的时候感觉比较合适(对此,官方文档是这样解释的:The QStyledItemDelegate class provides display and editing facilities for data items from a model.)。也就是说,如果想要在load的时候就显示出来控件,必须写在void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;里;如果控件需要有相应的动作,就需要写在editorEvent

        如果delegate没有支持为你的数据类型进行绘制,或者你希望自己绘制item,那么就可以继承QStyleItemDelegate类,并且重写paint()或者还需要重写sizeHit()函数。paint()函数会被每一个item独立调用,而sizeHint()函数则可以定义每一个item的大小。在重写paint()函数的时候,通常需要用if语句找到你需要进行渲染的诗句类型并进行绘制,其他的数据类型需要调用父类的实现进行绘制。

继承QStyledItemDelegate需要实现以下函数:

class MyDelegate: public QStyledItemDelegate
{
    //创建你编辑时候的控件,返回修改数据的组件
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const  QModelIndex &index) const;

    //编辑的时候设置数据到上面创建的editor中。
    void setEditorData(QWidget *editor, const QModelIndex &index) const; 

    //编辑完成,保存数据到model中
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;

    //设置编辑控件的位置和大小、样式等(保证editor显示在item view的合适位置以及大小)
    void updateEditorGeometry ( QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
}

例如,添加一个进度条控件:

void WidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 1) {
        int progress = index.data().toInt();
        QStyleOptionProgressBar progressBarOption;
        progressBarOption.rect = option.rect;
        progressBarOption.minimum = 0;
        progressBarOption.maximum = 100;
        progressBarOption.progress = progress;
        progressBarOption.text = QString::number(progress) + "%";
        progressBarOption.textVisible = true;
        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
      } else
        QStyledItemDelegate::paint(painter, option, index);
}

1.3 Model/View的基本原理

1、数据(Data)是实际的数据,如数据库的一个数据表或 SQL查询结果,内存中的一个StringList,或磁盘文件结构等。

2、视图或视图组件(View)是屏幕上的界面组件,视图从数据模型获得每个数据项的模型索引(model index),通过模型索引获取数据,然后为界面组件提供显示数据,Qt提供一些现成的数据视图组件,如QListView、QTreeView 和QTableView等。

3、模型或数据模型(Model)与实际数据通信,并为视图组件提供数据接口。它从原始数据提取需要的内容,用于视图组件进行显示和编辑。Qt中有一些预定义的数据模型,如QStringListModel
可作为StringList的数据模型,QSqlTableModel 可以作为数据库中一个数据表的数据模型。

        模型(Model)与数据源(Data)通信;视图(View)从模型(Model)中获取模型索引;在标准视图中,代理(delegate)渲染数据项。编辑项时,代理将直接使用模型索引(model index)与模型通信。模型、视图和代理之间使用信号和槽通信。当源数据发生变化时,数据模型发射信号通知视图组件:当用户在界面上操作数据时,视图组件发射信号表示这些操作信息;当编辑数据时,代理发射信号告知数据模型和视图组件编辑器的状态。

所有的基于项数据(item data)的数据模型(Model)都基于QAbstractltemModel类,此类定义了视图和代理访问数据的接口。数据本身不必存储在模型中;它可以保存在由单独的类、文件、数据库或其他应用程序组件提供的数据结构或存储库中。QabstracteModel提供了一个数据接口,该接口足够灵活,可以处理以table、list和tree的形式表示数据的视图。

Qt提供了一些现成的模型,可用于处理数据项:

  • QStringListModel 用于处理QString列表的数据模型类
  • QStandardItemModel 标准的基于项数据的数据模型类,管理更复杂的树结构,每个项数据内都可以包含任意类型的数据
  • QFileSystemModel 提供有关本地文件系统中的文件和目录的信息,文件系统模型类
  • QSqlQueryModel 用于数据库sql查询结果的数据模型类
  • QSqlTableModel 用于数据库中一个数据表的数据模型类
  • QSqlRelationalTableModel 用于关系型数据表的数据模型类
  • QSortFilterProxyModel 与其他数据模型结合,提供排序和过滤功能的数据模型类

如果这些标准模型不符合您的要求,您可以将QAbstractItemModel、QAbstractListModel或QAbstractTableModel子类化,以创建自己的自定义模型。

一般需要实现的子类为:

//获得模型的行数
int rowCount(const QModelIndex &parent) const;
//获得模型的列数
int columnCount(const QModelIndex &parent) const;
//向模型中设置数据
bool setData(const QModelIndex &index, const QVariant &value, int role );
//获得模型的数据
QVariant data(const QModelIndex &index, int role) const;
//设置模型的标题
QVariant headerData(int section, Qt::Orientation orientation, int role ) const;

2、代码是现实示例

2.1 设置样式文件

QString qssData = nullptr;
QFile fileqss(":/qss/QSSUITableView");
if(fileqss.open(QFile::ReadOnly))
{
        qssData = fileqss.readAll();
        fileqss.close();
}
ui->tableView->setStyleSheet(qssData);

2.2 set base attribute

    ui->tableView->verticalHeader()->hide();                                                   // 隐藏垂直头
    ui->tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);                       // 隐藏水平头
    //ui->tableView->horizontalHeader()->setStretchLastSection(true);                          // 设置随后一列拉伸
    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);         // 设置列平均分配
    //ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);  // 设置TreeWidget水平滚动和自适应宽度
    //ui->tableView->setColumnWidth(headersList.count() - 1, TITLE_FIXED_HEIGHT);              // 设置最后一列固定
    //ui->tableView->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);      // 行单选
    ui->tableView->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);         // 行多选 (单选QAbstractItemView::SingleSelection 多选:QAbstractItemView::MultiSelection)
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);                         // 不可编辑
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);                        // 设置选中模式为整行
    ui->tableView->setShowGrid(false);                                                         // 显示/隐藏网格线
    setFocusPolicy(Qt::FocusPolicy::NoFocus);                                                  // 设置选中之后无虚线焦点
    //horizontalHeader()->setMinimumSectionSize(100);                                          // 设置最小列宽
    //horizontalHeader()->setMaximumSectionSize(100);                                          // 设置最大列宽
    ui->tableView->verticalHeader()->setDefaultSectionSize(25);                                 // 可以设置tableview所有列的默认行高为15。
    //horizontalHeader()->setDefaultSectionSize(15);                                            // 可以设置tableview所有行的默认列宽为15。
    ui->tableView->setWordWrap(false);                                                         // 设置不自动换行
    setMouseTracking(true);                                                                     // 设置鼠标追踪

    // 设置第0列固定宽度
    /*
    ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(5, QHeaderView::Fixed);
    ui->tableView->setColumnWidth(0, 50);
    ui->tableView->setColumnWidth(2, 150);
    ui->tableView->setColumnWidth(3, 150);
    ui->tableView->setColumnWidth(4, 150);
    ui->tableView->setColumnWidth(5, 150);
    */

 2.3 设置model

    model = new QStandardItemModel;
    ui->tableView->setModel(model);

2.4 设置表头

    QStringList headerList;
    headerList<<"姓名"<<"QSpinBox"<<"QComboBox"<<"QPushButton"<<"CheckBox"<<"QPixmap"<<"QLineEdit"<<"ReadOnly"<<"Text"<<"ProcessBar"<<"DateEdit"<<"CustomWidget"<<"pDoubleProcessBar";
    model->setHorizontalHeaderLabels(headerList);

2.5 设置数据     

    model->setItem(0,0,new QStandardItem("张三"));
    model->setItem(1,0,new QStandardItem("李四"));
    model->setItem(2,0,new QStandardItem("王二"));
    model->setItem(3,0,new QStandardItem("小明同学"));

    model->setItem(0,1,new QStandardItem("1"));
    model->setItem(1,1,new QStandardItem("2"));
    model->setItem(2,1,new QStandardItem("3"));

    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);         // 选择一行

2.6 添加代理控件

2.6.1 添加 QSpinBox 代理 

    CUISpinBoxDelegate *pSpinBox = new CUISpinBoxDelegate(this);
    ui->tableView->setItemDelegateForColumn(1, pSpinBox);

2.6.2 添加 QComboBox 代理

    CUIComboBoxDelegate *pComboBox = new CUIComboBoxDelegate(this);
    ui->tableView->setItemDelegateForColumn(2, pComboBox);

2.6.3 添加 QPushButton 代理

    CUIMutipleButtonDeleagate *pMutipleBtn = new CUIMutipleButtonDeleagate(QStringList() << "修改" << "删除", this);

    ui->tableView->setItemDelegateForColumn(3, pMutipleBtn);

    connect(pMutipleBtn, &CUIMutipleButtonDeleagate::editData, [&](){
        QMessageBox::information(this, "提示", "这是一个编辑按钮");
    });
    connect(pMutipleBtn, &CUIMutipleButtonDeleagate::deleteData, [&](){
        QMessageBox::information(this, "提示", "这是一个删除按钮");
    });

2.6.4 添加 CheckBox 代理 

    /*CUITableHeaderView **/pTableHeaderView = new CUITableHeaderView(Qt::Horizontal, ui->tableView);

    connect(pTableHeaderView, &CUITableHeaderView::stateChanged, this, &MainWindow::headerStateChangedSlot);
    connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChangedSlot(QStandardItem*)));

    ui->tableView->setHorizontalHeader(pTableHeaderView);

    CUICheckBoxDelegate *pCheckedBox = new CUICheckBoxDelegate(this);
    ui->tableView->setItemDelegateForColumn(4, pCheckedBox);

2.6.5 添加 Pixmap 代理

    CUIPixmapDelegate *pPixmap = new CUIPixmapDelegate(this);
    ui->tableView->setItemDelegateForColumn(5, pPixmap);

2.6.6 添加 LineEdit 代理

CUILineEditDelegate *pLineEdit = new CUILineEditDelegate(this);

2.6.7 添加 ReadOnly 代理

    CUIOnlyReadDelegate *pReadOnly = new CUIOnlyReadDelegate(this);
    ui->tableView->setItemDelegateForColumn(7, pReadOnly);

2.6.8 添加 Text 代理 

    CUITextDelegate *pLabel = new CUITextDelegate(this);
    ui->tableView->setItemDelegateForColumn(8, pLabel);

2.6.9 添加 QProcessBar 代理

    CUIProcessBarDelegate *pProcessBar = new CUIProcessBarDelegate();
    ui->tableView->setItemDelegateForColumn(9, pProcessBar);
    
    QModelIndex index = model->index(0, 9, QModelIndex());
    model->setData(index,29);

2.6.10 添加 DateEdit 代理

    CUIDateEditDelegate *pDateEdit = new CUIDateEditDelegate();
    ui->tableView->setItemDelegateForColumn(10, pDateEdit);

2.6.11 添加 添加自定义窗口 代理 

    CUICustomDelegate *pCustomWidget = new CUICustomDelegate(this);
    ui->tableView->setItemDelegateForColumn(11, pCustomWidget);

2.6.12 添加 DoubleProcessBar 代理

    CUIDoubleProcessBarDelegate *pDoubleProcessBar = new CUIDoubleProcessBarDelegate(this);
    ui->tableView->setItemDelegateForColumn(12, pDoubleProcessBar);

2.7 获取某一单元格数据 

    //model->index(0, 1).data();

详细代码下载

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Qt的QTableView添加复选框,可以使用QCheckBox作为QTableView的单元格小部件,然后将其添加到表格的单元格。以下是一个简单的示例: ``` // 创建一个QStandardItemModel,该模型将在QTableView使用 QStandardItemModel *model = new QStandardItemModel(); // 构建表头 model->setHorizontalHeaderLabels(QStringList() << "Name" << "Age" << "Married"); // 添加数据行 QList<QStandardItem *> row1 = QList<QStandardItem *>() << new QStandardItem("John") << new QStandardItem("30") << new QStandardItem(); QList<QStandardItem *> row2 = QList<QStandardItem *>() << new QStandardItem("Jane") << new QStandardItem("25") << new QStandardItem(); // 创建QCheckBox小部件并将其设置为单元格的小部件 QCheckBox *marriedBox1 = new QCheckBox(); QCheckBox *marriedBox2 = new QCheckBox(); row1[2]->setCheckable(true); row1[2]->setCheckState(Qt::Unchecked); row1[2]->setData(QVariant::fromValue(marriedBox1), Qt::UserRole+1); row2[2]->setCheckable(true); row2[2]->setCheckState(Qt::Unchecked); row2[2]->setData(QVariant::fromValue(marriedBox2), Qt::UserRole+1); // 将数据行添加到模型 model->appendRow(row1); model->appendRow(row2); // 将模型设置为QTableView的模型 QTableView *tableView = new QTableView(); tableView->setModel(model); // 将QCheckBox小部件添加到单元格 tableView->setIndexWidget(model->index(0, 2), marriedBox1); tableView->setIndexWidget(model->index(1, 2), marriedBox2); ``` 在上面的示例,我们使用QStandardItemModel作为QTableView的模型,并将QCheckBox小部件添加到第三列的单元格。我们还将QCheckBox存储为QStandardItem的数据,以便稍后可以轻松地访问它。 最后,我们使用setIndexWidget函数将QCheckBox小部件添加到单元格

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值