实现:
1)继承代理类,实现自定义代理,网上很多教程,这里不再赘叙;
2)更加方便的方法,使用接口:
void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget);
其实QTableWidget的setCellWidget借口内部也是调用 setIndexWidget。
示例代码:
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
QStandardItemModel* model = new QStandardItemModel();
ui->tableView->setModel(model);
ui->tableView->setFocusPolicy(Qt::NoFocus); //去掉选中单元格时的虚框
model->setHorizontalHeaderLabels({"姓名", "年龄", "性别"});
model->setItem(0, 0, new QStandardItem("张三"));
model->setItem(0, 1, new QStandardItem("3"));
QComboBox* cmb = new QComboBox();
cmb->addItems({"男", "女"});
ui->tableView->setIndexWidget(model->index(0, 2), cmb);
model->setItem(1, 0, new QStandardItem("李四"));
model->setItem(1, 1, new QStandardItem("5"));
cmb = new QComboBox();
cmb->addItems({"男", "女"});
ui->tableView->setIndexWidget(model->index(1, 2), cmb);
}
使用QTableView,经常会有单选、多选、全选的需求,很多软件提供很简单、直观的方式——复选框。Qt中也可以很容易的进行实现。
1、编辑委托利用委托中重载createEditor(),激活QCheckBox,这个缺点是必须双击/选中,才能显示CheckBox控件。一般不满足实际中的直接显示的需要。
2、设置QAbstractTableModel的flags()函数,通过重写setData()与data()来实现。
3、使用QTableView的setIndexWidget(const QModelIndex &index, QWidget *widget)来实现。 此功能只应该用来显示可视区域内对应一个数据项的静态内容。如果想显示自定义的动态内容或执行自定义编辑器部件,子类化 QItemDelegate代替。也就是说,这只适合做静态数据的显示,不适合做一些插入、更新、删除操作的数据显示。
4、自定义委托,通过paint()方法来实现。这种方式比较复杂,但适合扩展,除了可以嵌入复选框,还可以通过绘制其它控件,按钮、图片等自定义风格。
下面就介绍最常用的方式,即方法二。
QMap用来保存选中行号以及对应的选中状态
QMap check_state_map;
setData()方法主要用来设置是否被选中,然后将对应的状态保存到QMap中;
QtableView中添加复选框
先创建一个Qt widgets 应用程序,并将mainwindow.cpp文件中修改为如下代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
#include
static bool createConnectionDateBase()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");; //创建QSQLdatabase对象,指定QT使用的哪一种SQL。
db.setDatabaseName("testSQL.db");
if(!db.open())
{
QMessageBox::critical(NULL,"数据库打开失败","打开数据库失败!",
QMessageBox::Cancel);
return false;
}
QSqlQuery query;
query.exec("create table TEST_SQL (id int(1) primary key,name char(200),age int(1),chenked int (1))");
query.exec("insert into TEST_SQL values(1,'测试1',18,0)");
query.exec("insert into TEST_SQL values(2,'测试2',19,0)");
query.exec("insert into TEST_SQL values(3,'测试3',20,0)");
return true;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
if(!createConnectionDateBase())
{
return;
}
model = new QSqlTableModel(this);
model->setTable("TEST_SQL");
model->setHeaderData(0,Qt::Horizontal,tr("ID号"));
model->setHeaderData(1,Qt::Horizontal,tr("姓名"));
model->setHeaderData(2,Qt::Horizontal,tr("年龄"));
model->select();
QTableView *view = new QTableView(this);
view->setModel(model);
setCentralWidget(view);
//ui->tableView->setModel(model);
}
MainWindow::~MainWindow()
{
delete ui;
}
现在开始往这个表中添加复选框,需要继承QSqlTableModel类,在工程中Add new,新建一个C++类,名字为myTableModel,然后在将生成的mytablemodel.h和metaoblemodel.cpp修改为如下:
#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H
#include
class myTableModel:public QSqlTableModel
{
Q_OBJECT
public:
myTableModel( QObject * parent = 0, QSqlDatabase db = QSqlDatabase() );
bool setData( const QModelIndex &index, const QVariant &value, int role );
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
};
#endif // MYTABLEMODEL_H
#include "mytablemodel.h"
QMap<int, Qt::CheckState> check_state_map;
int checkColumn = 3;//将复选框放到第几列,从0开始计数
myTableModel::myTableModel(QObject *parent, QSqlDatabase db)
{
}
bool myTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(!index.isValid())
return false;
if (role == Qt::CheckStateRole && index.column() == checkColumn)
{
check_state_map[index.row()] = (value == Qt::Checked ? Qt::Checked : Qt::Unchecked);return true;
}
else
return QSqlTableModel::setData(index, value,role);
}
QVariant myTableModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.column() != checkColumn )
{
return QSqlTableModel::data(index, role);
}
switch(role)
{
case Qt::CheckStateRole:
if(index.column() == checkColumn)
{
if (check_state_map.contains(index.row()))
{
return check_state_map[index.row()] == Qt::Checked ? Qt::Checked : Qt::Unchecked;
}
return Qt::Unchecked;
}
default:
return QVariant();
}
return QVariant();
}
Qt::ItemFlags myTableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
if (index.column() == checkColumn)
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
else
return QSqlTableModel::flags(index);
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
然后将mianwindow.cpp中包含该头文件 mytablemodel.h 然后将mianwindow.cpp的构造函数修改为如下:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
if(!createConnectionDateBase())
{
return;
}
model = new myTableModel(this);
model->setTable("TEST_SQL");
model->setHeaderData(0,Qt::Horizontal,tr("ID号"));
model->setHeaderData(1,Qt::Horizontal,tr("姓名"));
model->setHeaderData(2,Qt::Horizontal,tr("年龄"));
model->select();
QTableView *view = new QTableView(this);
view->setModel(model);
setCentralWidget(view);
//ui->tableView->setModel(model);
}