本文实现了使用QtableView控件来显示数据,数据源使用txt文本作为数据源,使用了QStandardItemModel作为数据模型来实现了对TableView空间的初始化,和对txt数据源的增删改查功能。
QT QtableView操作详解目录
1. 项目结构&软件界面
2. mainwindow.h文件
3. 构造函数
4. 打开文件
5. 实现监听事件
6. 初始化QtableView控件
7. 实现修改功能
8. 实现添加功能
9. 实现删除功能
10. 功能演示
雷总看了都说Nice的文章,看完记得点关注哈~
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
//引入头文件
#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 ¤t, const QModelIndex &previous);
void OnlineTreeViewDoubleClick(const QModelIndex & index);
private:
Ui::MainWindow *ui;
//初始化
mythread * thread;
//update的行
QString strUpItem="";
};
#endif // MAINWINDOW_H
ui->setupUi(this);
//构造函数
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类似
void MainWindow::on_Button_File_clicked()
{
/*
//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()<lineEdit_5->setText(fileName);
//QString fileName = QFileDialog::getExistingDirectory(NULL,"caption",".");
//ui->lineEdit_5->setText(fileName);
//6. 初始化QtableView控件
ioDemo();
}
监听鼠标点击单元格事件,用来在删除操作或者修改操作的时候获取选中的单元格进行操作。
第一个if是用来获取某一个单元格的X Y位置以及对应的Value值。
for 中的 3对应着 tableview的列,因为本文数据源有三列所以就直接写死了,后期需要可以设置两个全局变量代替。
最上方注释的代码是原型代码。
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
/*
//原型代码
//选择单元格变化时的响应
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()<itemFromIndex(current);
//this->LabCellText->setText ("单元格内容:"+aItem->text());
qDebug()<<"单元格内容:"<text();
QFont font=aItem->font();
qDebug()<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.单元格内容:"<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.单元格内容:"<text();
strUpItem += aItem->text();
}
qDebug()<<"3.单元格所选内容:" << strUpItem;
*/
}
QAbstractItemView参考:Qt QStandardItemModel(1.超级详细用法)_双子座断点的博客-CSDN博客_qstandardmodel
QAbstractItemView查找函数参考:Qt QStandardItemModel(2.超级详细函数)_双子座断点的博客-CSDN博客_qstandarditemmodel点击事件
修改样式参考:https://blog.csdn.net/QIJINGBO123/article/details/84186352
这块因为编码的问题所以全局默认bgk,在进行File文件操作的时候使用的是utf-8格式避免乱码。
下方数据模型设置部分需要添加函数可以点击QAbstractItemView查找函数进行参考查看
//初始化view
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()<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);//禁止选择多行
}
在修改&添加&删除操作过程中需要小心 ‘\n’ 换行符,因为如果修改完数据多添加一个换行符会导致下次的操作行数+2。
如果进行删除操作的话,删除会导致数据删除换行符还有存留。
添加操作的话可能会导致添加完后再次添加可能会添加至下下行。
//修改某一行代码
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;ilineEdit_4->text()); //"Hello!"是要替换的内容
stream<lineEdit_4->text()); //"Hello!"是要替换的内容
stream<
void MainWindow::on_pushButton_clicked()
{
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();
}
//删除某一行数据
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();
QMaprowMap;
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();
QMaprowMap;
foreach (QModelIndex index, IndexList)
{
if(! index.isValid()) return;
if(index.column()!=0) continue;
rowMap.insert(index.row(),0);
}
QMapIterator Iterator(rowMap);
Iterator.toBack();
while(rowMapIterator.hasPrevious())
{
rowMapIterator.previous();
int rowm=rowMapIterator.key();
qDebug()<<"del row..."<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
本文代码就不放出来了,自己加油加油照着做就可以做出来了。
本文借鉴参考: Qt QStandardItemModel用法(超级详细),其它博客就别瞎看了,参考作者的文章和C语言网的这篇文章是最正确的。
其它文章 :
QT TextEdit控件_双子座断点的博客-CSDN博客_qt textedit
QT QComboBox使用详解_双子座断点的博客-CSDN博客
QT QtableView操作详解_双子座断点的博客-CSDN博客_qtableview增删改查
Qt QStandardItemModel(1.超级详细用法)_双子座断点的博客-CSDN博客_qstandardmodel
Qt QStandardItemModel(2.超级详细函数)_双子座断点的博客-CSDN博客_qstandarditemmodel点击事件
QT QRadioButton使用详解_双子座断点的博客-CSDN博客_qt radiobutton
QT QLineEdit使用详解_双子座断点的博客-CSDN博客_qt qlineedit
Qt QMessageBox使用详解_双子座断点的博客-CSDN博客_qt message
QChart折线图、饼状图、条形图、曲线图_双子座断点的博客-CSDN博客_qchart样式
QChart属性详解_双子座断点的博客-CSDN博客_setanimationoptions
QCharts QValueAxis使用_双子座断点的博客-CSDN博客_qvalueaxis
Qt 5 等待提示框(开源 动态图)_双子座断点的博客-CSDN博客_qt 等待对话框
QtDataVisualization 数据3D可视化_双子座断点的博客-CSDN博客_qtdatavisualization
QT QLabel控件(使用详解)_双子座断点的博客-CSDN博客_qt label