QTableView编程——Model/View架构
基础知识
- 添加表头
//准备数据模型
QStandardItemModel *student_model = new QStandardItemModel();
student_model->setHorizontalHeaderItem(0, new QStandardItem(QObject::tr("Name")));
student_model->setHorizontalHeaderItem(1, new QStandardItem(QObject::tr("NO.")));
student_model->setHorizontalHeaderItem(2, new QStandardItem(QObject::tr("Sex")));
student_model->setHorizontalHeaderItem(3, new QStandardItem(QObject::tr("Age")));
student_model->setHorizontalHeaderItem(4, new QStandardItem(QObject::tr("College")));
//利用setModel()方法将数据模型与QTableView绑定
ui->student_tableview->setModel(student_model);
- 设置表格属性
//设置列宽不可变动,即不能通过鼠标拖动增加列宽
ui->student_tableview->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
ui->student_tableview->horizontalHeader()->setResizeMode(1, QHeaderView::Fixed);
ui->student_tableview->horizontalHeader()->setResizeMode(2, QHeaderView::Fixed);
ui->student_tableview->horizontalHeader()->setResizeMode(3, QHeaderView::Fixed);
ui->student_tableview->horizontalHeader()->setResizeMode(4, QHeaderView::Fixed);
//设置表格的各列的宽度值
ui->student_tableview->setColumnWidth(0,100);
ui->student_tableview->setColumnWidth(1,100);
ui->student_tableview->setColumnWidth(2,100);
ui->student_tableview->setColumnWidth(3,100);
ui->student_tableview->setColumnWidth(4,100);
//默认显示行头,如果你觉得不美观的话,我们可以将隐藏
ui->student_tableview->verticalHeader()->hide();
//设置选中时为整行选中
ui->student_tableview->setSelectionBehavior(QAbstractItemView::SelectRows);
//设置表格的单元为只读属性,即不能编辑
ui->student_tableview->setEditTriggers(QAbstractItemView::NoEditTriggers);
//如果你用在QTableView中使用右键菜单,需启用该属性
ui->tstudent_tableview->setContextMenuPolicy(Qt::CustomContextMenu);
- 动态添加行
//在第一行添加学生张三的个人信息(setItem函数的第一个参数表示行号,第二个表示列号,第三个为要显示的数据)
student_model->setItem(0, 0, new QStandardItem(“张三"));
student_model->setItem(0, 1, new QStandardItem("20120202"));
student_model->setItem(0, 2, new QStandardItem("男"));
student_model->setItem(0, 3, new QStandardItem("18"));
student_model->setItem(0, 4, new QStandardItem("土木学院"));
- 设置数据显示的样式
//设置单元格文本居中,张三的数据设置为居中显示
student_model->item(0, 0)->setTextAlignment(Qt::AlignCenter);
student_model->item(0, 1)->setTextAlignment(Qt::AlignCenter);
student_model->item(0, 2)->setTextAlignment(Qt::AlignCenter);
student_model->item(0, 3)->setTextAlignment(Qt::AlignCenter);
student_model->item(0, 4)->setTextAlignment(Qt::AlignCenter);
//设置单元格文本颜色,张三的数据设置为红色
student_model->item(0, 0)->setForeground(QBrush(QColor(255, 0, 0)));
student_model->item(0, 1)->setForeground(QBrush(QColor(255, 0, 0)));
student_model->item(0, 2)->setForeground(QBrush(QColor(255, 0, 0)));
student_model->item(0, 3)->setForeground(QBrush(QColor(255, 0, 0)));
student_model->item(0, 4)->setForeground(QBrush(QColor(255, 0, 0)));
//将字体加粗
student_model->item(0, 0)->setFont( QFont( "Times", 10, QFont::Black ) );
student_model->item(0, 1)->setFont( QFont( "Times", 10, QFont::Black ) );
student_model->item(0, 2)->setFont( QFont( "Times", 10, QFont::Black ) );
student_model->item(0, 3)->setFont( QFont( "Times", 10, QFont::Black ) );
student_model->item(0, 4)->setFont( QFont( "Times", 10, QFont::Black ) );
//设置排序方式,按年龄降序显示
student_model->sort(3, Qt::DescendingOrder);
功能实现
实现功能
- 实现TableView中的单元格和单元格直接的拖拽替换
- 如果整行为空的时候,会自动删除该行
- 如果拖拽的表格的底部,那么自动增加一行
01 随意拖拽替换
替换前:
替换后:
02 整行为空 自动删除空行
03 拖拽到底部自动增加一行
代码实现
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "MyTableModel.h"
#include "MyStandardItemModel.h"
#include "MyTableView.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initMyStandardItemModel();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initMyStandardItemModel()
{
//QStandardItemModel类提供用于存储自定义数据的通用模型
MyStandardItemModel* model = new MyStandardItemModel(this);
QTableView *view=ui->tableViewB;
view->setModel(model);
QStringList headerList;
headerList << "Driver" << "Dest" << "Choose";
model->setHorizontalHeaderLabels(headerList);
model->setItem(0,2, new QStandardItem("driclk1"));
model->setItem(1,2, new QStandardItem("driclk2"));
model->setItem(2,2, new QStandardItem("driclk3"));
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setDragEnabled(true);
view->setDefaultDropAction(Qt::MoveAction);//不是必要的
view->setDragDropMode(QAbstractItemView::DragDrop);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initMyStandardItemModel();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MyStandardItemModel.cpp
#include "MyStandardItemModel.h"
#include <QMimeData>
#include <QDebug>
MyStandardItemModel::MyStandardItemModel(QObject *parent)
: QStandardItemModel(parent)
{
}
Qt::ItemFlags MyStandardItemModel::flags(const QModelIndex &index) const
{
if (index.isValid())
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | QStandardItemModel::flags(index);
return QStandardItemModel::flags(index);
}
Qt::DropActions MyStandardItemModel::supportedDropActions() const
{
return Qt::MoveAction | QStandardItemModel::supportedDropActions();
}
QMimeData *MyStandardItemModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *data=QStandardItemModel::mimeData(indexes);
if(data){
// parent mimeData中已判断indexes有效性,无效的会返回nullptr
// 也可以把信息放到model的mutable成员中
data->setData("row",QByteArray::number(indexes.at(0).row()));
data->setData("col",QByteArray::number(indexes.at(0).column()));
}
return data;
}
bool MyStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
if(!data||action!=Qt::MoveAction)
return false;
//这里没有判断toint ok(数据转换有效性) dri
const QModelIndex old_index=index(data->data("row").toInt(),
data->data("col").toInt());
const QModelIndex current_index=parent;
//可以先对index有效性进行判断,无效返回false,此处略过 dest
QStandardItem *old_item=takeItem(old_index.row(),old_index.column());
QStandardItem *current_item=takeItem(current_index.row(),current_index.column());
if (!parent.isValid()) {
appendRow(QList<QStandardItem *>() << old_item);
} else {
//交换两个item
setItem(old_index.row(),old_index.column(),current_item);
setItem(current_index.row(),current_index.column(),old_item);
}
for (int row = 0; row < rowCount(); ++row) {
if (isRowEmpty(row)) {
removeRow(row);
}
}
// 打印修改后的 model 数据
for (int row = 0; row < rowCount(); row++) {
for (int col = 0; col < columnCount(); col++) {
QModelIndex index = this->index(row, col);
QString data = this->data(index, Qt::DisplayRole).toString();
qDebug() << "Row " << row << ", Column " << col << ": " << data;
}
}
return true;
}
bool MyStandardItemModel::isRowEmpty(int row)
{
for (int column = 0; column < columnCount(); ++column) {
QModelIndex index = this->index(row, column);
if (index.isValid() && !index.data().toString().isEmpty()) {
// 如果有一列数据不为空,说明这一行不为空
return false;
}
}
// 所有列数据都为空,说明这一行为空
return true;
}
MyStandardItemModel.h
#ifndef MYSTANDARDITEMMODEL_H
#define MYSTANDARDITEMMODEL_H
#include <QStandardItem>
#include <QStandardItemModel>
class MyStandardItemModel : public QStandardItemModel
{
Q_OBJECT
public:
explicit MyStandardItemModel(QObject *parent = nullptr);
// 允许的操作,加上drag drop
Qt::ItemFlags flags(const QModelIndex &index) const override;
// 允许move
Qt::DropActions supportedDropActions() const override;
// drag时携带的信息 存放拖拽的数据
QMimeData *mimeData(const QModelIndexList &indexes) const override;
// drop时根据drag携带的信息进行处理
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
bool isRowEmpty(int row);
};
#endif // MYSTANDARDITEMMODEL_H
参考资料
Qt QTableView 表格内添加控件_qt中tableview加入其他控件_师从名剑山的博客-CSDN博客
QTableView拖拽交换行、列、单元格_龚建波的博客-CSDN博客