QTableView编程——Model/View架构(单元格随意拖拽交换)

该文详细介绍了如何使用Qt的QTableView组件构建Model/View架构,包括设置表头、表格属性、数据模型,以及如何实现表格内的单元格拖拽替换功能,当行为空时自动删除,拖拽到底部时自动增加新行。同时,文中提供了关键代码示例来辅助理解。
摘要由CSDN通过智能技术生成

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 随意拖拽替换

替换前:

image-20230515212606637

替换后:

image-20230515212636894

02 整行为空 自动删除空行

image-20230515212743822

03 拖拽到底部自动增加一行

image-20230515212804885

代码实现

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博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-特立独行的猪-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值