Qt QTableView 表格内添加控件
书接上回,之前写了怎么在表格的表头添加复选框,Qt QHeaderView 添加复选框_师从名剑山的博客-CSDN博客。这次来写怎么给表格内添加控件。
往表格里添加控件主要有两种方法,第一种是使用代理,QItemDelegate
,重载其createEditor
这个函数,但是这个有个缺点,就是必须双击进入编辑模式才能修改,第二种方式就是setIndexWidget
,这个要更好。
1. QItemDelegate
第一种方式是使用代理的方式,重载createEditor
。之前一直知道QTableView有一种代理的方式,但是觉得这种方式很复杂,于是就基本没有用这个方法,最近刚好用到,就去了解了一下。
对于createEditor
,我的理解是创建一个对表格的编辑,所以就需要双击之后才会显示,同样。这里参考QT的文档里对于这种方法的解释,同时在QT的示例spin box delegate
中,有比较详尽的解释。
截取其中的一部分,对于createEditor
、setEditorData
和setModelData
这几个函数的用处。
createEditor
: 创建一个编辑器小部件,并将其直接显示在项目的顶部。
setEditorData
: 用来自model里的数据来填充editor。
setModelData
: 用editor的数据来填充model。
代码如下:
delegate.h
#ifndef DELEGATE_H
#define DELEGATE_H
#include <QItemDelegate>
#include <QCheckBox>
#include <QApplication>
class Delegate : public QItemDelegate
{
public:
Delegate(QObject* parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
// void setEditorData(QWidget *editor, const QModelIndex &index) const;
// void setModelData(QWidget *editor, QAbstractItemModel *model,
// const QModelIndex &index) const;
};
#endif // DELEGATE_H
delegate.cpp
#include "delegate.h"
Delegate::Delegate(QObject *parent)
{
}
void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QItemDelegate::paint(painter, option, index);
}
QSize Delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QItemDelegate::sizeHint(option, index);
}
QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.isValid() && index.column() == 0) {
QCheckBox* checkBox = new QCheckBox(parent);
checkBox->installEventFilter(const_cast<Delegate*> (this));
return checkBox;
} else {
return QItemDelegate::createEditor(parent, option, index);
}
}
由于此处添加的是一个复选框,所以没有重载setEditorData
和setModelData
这两个函数,只是重载了createEditor
这个函数。
具体的效果图如下:
2. setIndexWidget
第二种方式是使用这个API : void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget)
index
代表单元格所在的下标,widget
代表你需要添加的窗口。
代码如下:
tableviewModel = new QStandardItemModel;
ui->tableView->setModel(tableviewModel);
QStringList headerList;
headerList<<"姓名"<<"性别"<<"年龄";
tableviewModel->setHorizontalHeaderLabels(headerList);
tableviewModel->setItem(0,1,new QStandardItem("张三"));
tableviewModel->setItem(1,1,new QStandardItem("李四"));
tableviewModel->setItem(2,1,new QStandardItem("王二"));
QStandardItem* item = new QStandardItem();
QCheckBox *checkBox = new QCheckBox();
tableviewModel->setItem(0, 0, item);
ui->tableView->setIndexWidget(tableviewModel->index(0, 0), checkBox );
但是这里有一个缺点,如果直接插入进去,会出现没办法控制这个控件的位置,这个控件默认在最左边,如下图:
3. setIndexWidget + setLayout
根据上面出现的情况,可以先创建一个widget
,然后再创建一个布局,在把你需要添加的控件加到这个布局里去,然后再根据你的需求来布局。
代码如下:
tableviewModel = new QStandardItemModel;
ui->tableView->setModel(tableviewModel);
QStringList headerList;
headerList<<"姓名"<<"性别"<<"年龄";
tableviewModel->setHorizontalHeaderLabels(headerList);
tableviewModel->setItem(0,1,new QStandardItem("张三"));
tableviewModel->setItem(1,1,new QStandardItem("李四"));
tableviewModel->setItem(2,1,new QStandardItem("王二"));
QStandardItem* item = new QStandardItem();
QWidget* checkWidget = new QWidget();
QHBoxLayout* hLayout = new QHBoxLayout;
QCheckBox *checkBox = new QCheckBox(checkWidget);
hLayout->setContentsMargins(10, 0, 0, 0);
hLayout->addWidget(checkBox);
checkWidget->setLayout(hLayout);
tableviewModel->setItem(0, 0, item);
ui->tableView->setIndexWidget(tableviewModel->index(0, 0), checkWidget);
效果图如下: