QT QtableView操作详解

简介: 本文实现了使用QtableView控件来显示数据,数据源使用txt文本作为数据源,使用了QStandardItemModel作为数据模型来实现了对TableView空间的初始化,和对txt数据源的增删改查功能。

本文作者原创首发于CSDN,本文原创请勿转载

版权声明:本文为CSDN博主「双子座断点」的原创文章,遵循CC 4.0 BY-SA版权协议。
原文链接:https://blog.csdn.net/qq_37529913/article/details/110127940
1. 项目结构&软件界面
图片.png
图片.png
图片.png
2. mainwindow.h文件

#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QStandardItemModel>
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QModelIndex>
#include <QFileDialog>
#include <functional>
#include <QItemSelectionModel>
//引入头文件
#include "mythread.h"
 
//加入GBK申明,否则中文乱码 全局使用GBK文件操作因为有中文所以使用utf-8
#pragma execution_character_set("gbk")
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
    void ioDemo();    //初始化 删除修改添加之后也会调用初始化函数
    void deleteOnelineInFile(int nNumLine, QString &filename); //删除函数
    void DeleteOneline(int nNum, QString &strall);             //删除函数
 
 
    QLabel *LabCurFile;    //当前文件
    QLabel *LabCellPos;    //当前单元格行列号
    QLabel *LabCellText; //当前单元格内容
    /* 创建数据模型 */
    QStandardItemModel* model = new QStandardItemModel();
    QItemSelectionModel *theSelection; //选择模型
 
private slots:
    void on_tableView_activated(const QModelIndex &index);
 
    void on_pushButton_clicked();
 
    void on_pushButton_2_clicked();
 
    void on_pushButton_3_clicked();
 
    void on_pushButton_4_clicked();
 
    void on_Button_File_clicked();
 
    //当前选择单元格发生变化
    void on_currentChanged(const QModelIndex &current, const QModelIndex &previous);
 
    void OnlineTreeViewDoubleClick(const QModelIndex & index);
 
private:
    Ui::MainWindow *ui;
 
    //初始化
    mythread * thread;
 
    //update的行
    QString strUpItem="";
};
#endif // MAINWINDOW_H

3. 构造函数

 
    //构造函数
    thread = new mythread;  //分配空间
    //关联信号获取结束线程信号
    connect(thread, &mythread::isDone, this, &MainWindow::addSave);
 
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//不可编辑
    //ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选中模式为选中行
    //ui->tableView->setSelectionMode( QAbstractItemView::SingleSelection);//设置选中单个
    //QTableWidget类似

4. 打开文件

{
    /*
    //Button_File
    //定义文件对话框类
    QFileDialog *fileDialog = new QFileDialog(this);
    //定义文件对话框标题
    fileDialog->setWindowTitle(QStringLiteral("选中文件"));
    //设置默认文件路径
    fileDialog->setDirectory(".");
    //设置文件过滤器
    fileDialog->setNameFilter(tr("File(*.*)"));
    //设置可以选择多个文件,默认为只能选择一个文件QFileDialog::ExistingFiles
    fileDialog->setFileMode(QFileDialog::ExistingFiles);
    //设置视图模式
    fileDialog->setViewMode(QFileDialog::Detail);
    //打印所有选择的文件的路径
    QStringList fileNames;
    if (fileDialog->exec()) {
        fileNames = fileDialog->selectedFiles();
        qDebug()<<fileNames;
    }
    */
    //QFile writeFile("E:/QT/Creator/QT_MySQL/aa.txt");    //PATH是自定义写文件的地址
 
    QString fileName = QFileDialog::getOpenFileName(this,"文件对话框!",".","Text files (*.txt);;Any files (*)");
    ui->lineEdit_5->setText(fileName);
 
    //QString fileName = QFileDialog::getExistingDirectory(NULL,"caption",".");
    //ui->lineEdit_5->setText(fileName);
    //6. 初始化QtableView控件
    ioDemo();
}

5. 实现监听事件


    第一个if是用来获取某一个单元格的X Y位置以及对应的Value值。

    for 中的 3对应着 tableview的列,因为本文数据源有三列所以就直接写死了,后期需要可以设置两个全局变量代替。

    最上方注释的代码是原型代码。
{
    /*
    //原型代码
    //选择单元格变化时的响应
    if (current.isValid())
    {
        LabCellPos->setText (QString::asprintf ("当前单元格:%d 行,%d 列", current.row(),current.column()));
        QStandardItem* aItem=theModel->itemFromIndex(current);
        this->LabCellText->setText ("单元格内容:"+aItem->text());
        QFont font=aItem->font();
        ui->actFontBold->setChecked(font.bold());
    }
    */
    if (current.isValid())
    {
        //LabCellPos->setText (QString::asprintf ("当前单元格:%d 行,%d 列", current.row(),current.column()));
        qDebug()<<"当前单元格:";
        qDebug()<<QString::number(current.row())<<" 行,";
        //qDebug()<<QString::number(current.column())<<" 列";
        QStandardItem* aItem=model->itemFromIndex(current);
        //this->LabCellText->setText ("单元格内容:"+aItem->text());
        qDebug()<<"单元格内容:"<<aItem->text();
        QFont font=aItem->font();
        qDebug()<<font.bold();
        //ui->actFontBold->setChecked(font.bold());
    }
    strUpItem="";
    for(int i=0;i<3;i++){
        QModelIndex rootIndex = ui->tableView->model()->index(current.row(), i);//最顶层item的index
        QStandardItem* aItem=model->itemFromIndex(rootIndex);
        qDebug()<<"2.单元格内容:"<<aItem->text();
        strUpItem += aItem->text();
    }
    qDebug()<<"2.单元格所选内容:" << strUpItem;
    /*
    strUpItem="";
    for(int i=0;i<3;i++){
        QModelIndex rootIndex = ui->tableView->model()->index(-1, i);//最顶层item的index
        QStandardItem* aItem=model->itemFromIndex(rootIndex);
        qDebug()<<"3.单元格内容:"<<aItem->text();
        strUpItem += aItem->text();
    }
    qDebug()<<"3.单元格所选内容:" << strUpItem;
    */
}

6. 初始化QtableView控件
QAbstractItemView参考:Qt QStandardItemModel(1.超级详细用法)_双子座断点的博客-CSDN博客_qstandardmodel

QAbstractItemView查找函数参考:Qt QStandardItemModel(2.超级详细函数)_双子座断点的博客-CSDN博客_qstandarditemmodel点击事件

修改样式参考:https://blog.csdn.net/QIJINGBO123/article/details/84186352

    下方数据模型设置部分需要添加函数可以点击QAbstractItemView查找函数进行参考查看
void MainWindow::ioDemo()
{
 
    QFile file(ui->lineEdit_5->text());
    ui->tableView->setModel(model);
 
    /* 设置表格标题行(输入数据为QStringList类型) */
    model->setHorizontalHeaderLabels({"学号", "姓名", "考试题目"});
 
    /* 自适应所有列,让它布满空间 */
    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
 
    if(! file.open(QIODevice::ReadOnly|QIODevice::Text))
        qDebug()<<file.errorString();
    else
         qDebug()<<"openok";
    file.seek(0);
 
 
    QTextStream shuru(&file);
    shuru.setCodec("utf-8"); // 设置文件的编码格式为utf-8
    int ioInt=0;
    QString strID,strName,School;
 
    while(! shuru.atEnd())
    {
        QString line=shuru.readLine();
        qDebug()<<line;
 
        model->setItem(ioInt, 0, new QStandardItem(line.left(1)));
        model->setItem(ioInt, 1, new QStandardItem(line.mid(1,3)));
        model->setItem(ioInt, 2, new QStandardItem(line.mid(4,8)));
        ioInt++;
    }
    /* 设置表格视图数据 */
    ui->tableView->setModel(model);
 
    /* 显示 */
    ui->tableView->show();
 
    file.close();
 
    //数据模型
    theSelection = new QItemSelectionModel (model) ;//选择模型
    connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)), this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
    ui->tableView->setSelectionModel(theSelection); //设置选择模型
    ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    //ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选中模式为选中行
    ui->tableView->setSelectionMode ( QAbstractItemView::SingleSelection);//禁止选择多行
 
}

7. 实现修改功能


    如果进行删除操作的话,删除会导致数据删除换行符还有存留。

    添加操作的话可能会导致添加完后再次添加可能会添加至下下行。
void MainWindow::on_pushButton_3_clicked()
{
        QString strAll;
        QStringList strList;
        QFile readFile(ui->lineEdit_5->text());
        if(readFile.open((QIODevice::ReadOnly|QIODevice::Text)))
        {
            //把文件所有信息读出来
            QTextStream stream(&readFile);
            stream.setCodec("utf-8"); // 设置文件的编码格式为utf-8
            strAll=stream.readAll();
        }
        readFile.close();
        QFile writeFile(ui->lineEdit_5->text());
        if(writeFile.open(QIODevice::WriteOnly|QIODevice::Text))
        {
                QTextStream stream(&writeFile);
                stream.setCodec("utf-8"); // 设置文件的编码格式为utf-8
                strList=strAll.split("\n");           //以换行符为基准分割文本
                for(int i=0;i<strList.count();i++)    //遍历每一行
                {
                    //strUpItem 全局变量,在鼠标选中行后自动获取value
                    if(strList.at(i).contains(strUpItem))
                    {
                        if(i==strList.count()-1){
                            QString tempStr=strList.at(i);
                            tempStr.replace(0,tempStr.length(),ui->lineEdit_4->text());   //"Hello!"是要替换的内容
                            stream<<tempStr<<'\n';
                        }
                        else{
                            QString tempStr=strList.at(i);
                            tempStr.replace(0,tempStr.length(),ui->lineEdit_4->text());   //"Hello!"是要替换的内容
                            stream<<tempStr<<'\n';
                        }
                    }
                    //如果没有找到要替换的内容,照常写入
                    else
                    {
                        if(i==strList.count()-1)
                        {
                           stream<<strList.at(i);
                        }
                        else
                        {
                           stream<<strList.at(i)<<'\n';//添加<<'\n'换行
                        }
                    }
                }
        }
        writeFile.close();
        ioDemo();
}

8. 实现添加功能

{
    QFile file(ui->lineEdit_5->text());
    QString n1;
       if (file.open(QIODevice::ReadWrite | QIODevice::Append))
       {
           QTextStream txtOutput(&file);
           txtOutput.setCodec("utf-8"); // 设置文件的编码格式为utf-8
           n1="\n"+ui->lineEdit->text()+" "+ui->lineEdit_2->text()+" "+ui->lineEdit_3->text();
           txtOutput << n1 << endl;
           file.close();
       }
    file.close();
    ioDemo();
}

9. 实现删除功能

void MainWindow::on_pushButton_2_clicked()
{
    QString str=ui->lineEdit_5->text();
    deleteOnelineInFile(ui->tableView->currentIndex().row(),str);
    //重新初始化视图
    ioDemo();
 
    //删除多行
    /*
        出自https://blog.csdn.net/qq_40450386/article/details/82904934
        QItemSelectionModel *model_selection = ui->tableView->selectionModel();
        QModelIndexList IndexList= model_selection->selectedIndexes();
        QMap<int,int>rowMap;
        foreach (QModelIndex index, IndexList)
        {
            //处理略  ...  可以读取、修改其内容;
        }
        上面代码中QModelIndexList记录的是所有选中的item的index,而不是行的index,不管你的选中模式是行还是item;
        如果想对整行处理的话,需要避免对同一行多次操作;比如可以index.column()==0时进行操作处理;
        如果删除选中的多行,更需要当心进坑!model.removeRow(row)之后,之后的行号就变了(减少1),可不幸的是,选中记录里的行号没有变化,还是原来的行号,再进行删除就删错行了。(比如,要删除2,4行,删了第2行后,原来的第4行变成了第3行,可是你删除的还是记录里的第4行!)所以删除多个行时,要从后往前删除,先删除行号大的,对小的没影响。
        可以用Qmap记录删除的行,因为他是排序的,省去麻烦
        删除多行完整代码如下:
        QItemSelectionModel *model_selection = ui->tableView->selectionModel();
        QModelIndexList IndexList= model_selection->selectedIndexes();
        QMap<int,int>rowMap;
        foreach (QModelIndex index, IndexList)
        {
            if(! index.isValid()) return;
            if(index.column()!=0) continue;
            rowMap.insert(index.row(),0);
        }
        QMapIterator<int,int> Iterator(rowMap);
        Iterator.toBack();
        while(rowMapIterator.hasPrevious())
        {
            rowMapIterator.previous();
            int rowm=rowMapIterator.key();
            qDebug()<<"del row..."<<rowm;
            file_model->removeRow(rowm);
        }
    */
}
 
 
void MainWindow::deleteOnelineInFile(int nNumLine, QString &filename)
{
    //删除model中的一行视图数据
    model->removeRow(nNumLine);
    QString strall;
    QFile readfile(filename);
    if(readfile.open(QIODevice::ReadOnly))
    {
        QTextStream stream(&readfile);
        strall=stream.readAll();
    }
    readfile.close();
    DeleteOneline(nNumLine, strall);
 
    //删除File文件内的某一行数据
    QFile writefile(ui->lineEdit_5->text());
    if(writefile.open(QIODevice::WriteOnly))
    {
        QTextStream wrtstream(&writefile);
        // --\n
        wrtstream << strall;
    }
    writefile.close();
}
 
void MainWindow::DeleteOneline(int nNum, QString &strall)
{
    int nLine=0;
    int Index=0;
    //算出行数nLine
    while(Index!=-1)
    {
        Index=strall.indexOf('\n',Index+1);
        nLine++;
    }
 
    //如果是直接从位置0开始删除\n算一个字符"abc\nme\ndo" \n的index是3要删除3+1个字符,即index+1个
    if(nNum==0)
    {
        int nIndex=strall.indexOf('\n');
        strall.remove(0,nIndex+1);
    }
    else
    {
        int nTemp=nNum;
        int nIndex=0,nIndex2=0;
        while(nTemp--)
        {
            //
            nIndex=strall.indexOf('\n',nIndex+1);//这里会更新nIndex
            if(nIndex!=-1)//说明是有效的
            {
                nIndex2=strall.indexOf('\n',nIndex+1);
            }
        }
        //删除的行不是最后一行(从nIndex+1这个位置起nIndex2-nIndex个字符全部抹去)
        if(nNum<nLine-1)
        {
            strall.remove(nIndex+1, nIndex2-nIndex);//不用减一
        }
        //删除的是最后一行(从nIndex起始len-nIndex个字符全抹去)
        //不能从nIndex+1处开始,
        else if(nNum==nLine-1)
        {
            int len=strall.length();
            strall.remove(nIndex,len-nIndex);
        }
        else
        {
 
        }
 
    }
}

10. 功能演示
本文代码就不放出来了,自己加油加油照着做就可以做出来了。
图片.png

本文借鉴参考: Qt QStandardItemModel用法(超级详细),其它博客就别瞎看了,参考作者的文章和C语言网的这篇文章是最正确的。
图片.png
雷总看了都说Nice的文章,看完记得点关注哈~
图片.png

相关文章
|
2月前
|
数据库 开发者 Windows
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解-2
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解
|
2月前
|
XML 设计模式 JSON
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解-1
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解
|
8月前
《QT从基础到进阶·十》QTableView,QTableWidget,QLineEdit设置只读和输入限制
《QT从基础到进阶·十》QTableView,QTableWidget,QLineEdit设置只读和输入限制
169 0
|
8月前
《QT从基础到进阶·七》QTableView的使用
《QT从基础到进阶·七》QTableView的使用
99 0
|
SQL 数据库 计算机视觉
Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作
Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作
Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作
|
Web App开发 索引
Qt之QTableView显示富文本
简述 对于QTableView中的显示,我们前面介绍过很多种,其中包括:文本、进度条、复选框等,今天我们介绍一下关于富文本的显示。 可能绝大多数小伙伴会通过QAbstractTableModel中的data来实现,可是现实告诉我们,那是行不通的,那么我们如何去显示呢?请看正文。 简述 效果 源码 分析 效果 源码 下面我们使用QAbstrac
998 0
|
存储 程序员 C#
Python Qt GUI设计:QTableView、QListView、QListWidet、QTableWidget、QTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)
Python Qt GUI设计:QTableView、QListView、QListWidet、QTableWidget、QTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)
Python Qt GUI设计:QTableView、QListView、QListWidet、QTableWidget、QTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)
转载:QT QTableView用法小结
出自:   http://blog.chinaunix.net/uid-20382483-id-3518513.html   QTableView常用于实现数据的表格显示。下面我们如何按步骤实现学生信息表格: 一 添加表头     //准备数据模型     QStandardIte...
1212 0