網(wǎng)站首頁 編程語言 正文
QStandardItemModel 是標(biāo)準(zhǔn)的以項數(shù)據(jù)為單位的基于M/V模型的一種標(biāo)準(zhǔn)數(shù)據(jù)管理方式,Model/View 是Qt中的一種數(shù)據(jù)編排結(jié)構(gòu),其中Model代表模型,View代表視圖,視圖是顯示和編輯數(shù)據(jù)的界面組件,而模型則是視圖與原始數(shù)據(jù)之間的接口,通常該類結(jié)構(gòu)都是用在數(shù)據(jù)庫中較多,例如模型結(jié)構(gòu)負(fù)責(zé)讀取或?qū)懭霐?shù)據(jù)庫,視圖結(jié)構(gòu)則負(fù)責(zé)展示數(shù)據(jù),其條理清晰,編寫代碼便于維護(hù)。
QStandardItemModel組件通常會配合TableView
組件一起使用,當(dāng)數(shù)據(jù)庫或文本中的記錄發(fā)生變化時會自動同步到組件中,首先繪制UI界面。
其次綁定頂部ToolBar
菜單,分別對菜單增加對應(yīng)的功能屬性的描述等。
初始化構(gòu)造函數(shù): 當(dāng)程序運(yùn)行時,我們需要對頁面中的控件逐一初始化,并將Table表格與模型通過調(diào)用ui->tableView->setModel(model)
進(jìn)行綁定。
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QLabel> #include <QStandardItem> #include <QItemSelectionModel> #include <QFileDialog> #include <QTextStream> #include <QList> // 默認(rèn)構(gòu)造函數(shù) // https://www.cnblogs.com/lyshark MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化部分 model = new QStandardItemModel(3,FixedColumnCount,this); // 數(shù)據(jù)模型初始化 selection = new QItemSelectionModel(model); // Item選擇模型 // 為TableView設(shè)置數(shù)據(jù)模型 ui->tableView->setModel(model); // 設(shè)置數(shù)據(jù)模型 ui->tableView->setSelectionModel(selection); // 設(shè)置選擇模型 // 默認(rèn)禁用所有Action選項,只保留打開 ui->actionSave->setEnabled(false); ui->actionView->setEnabled(false); ui->actionAppend->setEnabled(false); ui->actionDelete->setEnabled(false); ui->actionInsert->setEnabled(false); // 創(chuàng)建狀態(tài)欄組件,主要來顯示單元格位置 LabCurFile = new QLabel("當(dāng)前文件:",this); LabCurFile->setMinimumWidth(200); LabCellPos = new QLabel("當(dāng)前單元格:",this); LabCellPos->setMinimumWidth(180); LabCellPos->setAlignment(Qt::AlignHCenter); LabCellText = new QLabel("單元格內(nèi)容:",this); LabCellText->setMinimumWidth(150); ui->statusbar->addWidget(LabCurFile); ui->statusbar->addWidget(LabCellPos); ui->statusbar->addWidget(LabCellText); //選擇當(dāng)前單元格變化時的信號與槽 connect(selection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex))); } MainWindow::~MainWindow() { delete ui; }
初始化時同時需要綁定一個on_currentChanged(QModelIndex,QModelIndex)
信號,當(dāng)用戶選中指定單元格時相應(yīng)用戶。
// 選擇單元格變化時的響應(yīng),通過在構(gòu)造函數(shù)中綁定信號和槽函數(shù)實(shí)現(xiàn)觸發(fā) // https://www.cnblogs.com/lyshark void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous) { Q_UNUSED(previous); if (current.isValid()) //當(dāng)前模型索引有效 { LabCellPos->setText(QString::asprintf("當(dāng)前單元格:%d行,%d列",current.row(),current.column())); //顯示模型索引的行和列號 QStandardItem *aItem; aItem=model->itemFromIndex(current); //從模型索引獲得Item this->LabCellText->setText("單元格內(nèi)容:"+aItem->text()); //顯示item的文字內(nèi)容 } }
當(dāng)頁面被初始化時,默認(rèn)界面如下:
打開并填充組件: 當(dāng)工具欄中打開文件被點(diǎn)擊后則觸發(fā),打開文件時通過aFile.open
打開,循環(huán)讀入文件,并將文件中的內(nèi)容逐行追加到QStringList fFileContent
中,當(dāng)追加完畢后,直接調(diào)用iniModelFromStringList(fFileContent);
完成對頁面TableView組件的初始化,并設(shè)置其他控件狀態(tài)為可點(diǎn)擊。
void MainWindow::on_actionOpen_triggered() { QString curPath=QCoreApplication::applicationDirPath(); // 獲取應(yīng)用程序的路徑 // 調(diào)用打開文件對話框打開一個文件 // https://www.cnblogs.com/lyshark QString aFileName=QFileDialog::getOpenFileName(this,"打開一個文件",curPath,"數(shù)據(jù)文件(*.txt);;所有文件(*.*)"); if (aFileName.isEmpty()) { return; // 如果未選擇文件則退出 } QStringList fFileContent; // 文件內(nèi)容字符串列表 QFile aFile(aFileName); // 以文件方式讀出 if (aFile.open(QIODevice::ReadOnly | QIODevice::Text)) // 以只讀文本方式打開文件 { QTextStream aStream(&aFile); // 用文本流讀取文件 ui->plainTextEdit->clear(); // 清空列表 // 循環(huán)讀取只要不為空 while (!aStream.atEnd()) { QString str=aStream.readLine(); // 讀取文件的一行 ui->plainTextEdit->appendPlainText(str); // 添加到文本框顯示 fFileContent.append(str); // 添加到StringList } aFile.close(); // 關(guān)閉文件 iniModelFromStringList(fFileContent); // 從StringList的內(nèi)容初始化數(shù)據(jù)模型 } // 打開文件完成后,就可以將Action全部開啟了 ui->actionSave->setEnabled(true); ui->actionView->setEnabled(true); ui->actionAppend->setEnabled(true); ui->actionDelete->setEnabled(true); ui->actionInsert->setEnabled(true); // 打開文件成功后,設(shè)置狀態(tài)欄當(dāng)前文件列 this->LabCurFile->setText("當(dāng)前文件:"+aFileName);//狀態(tài)欄顯示 }
如上iniModelFromStringList(fFileContent);
函數(shù)是后期增加的,我們需要自己實(shí)現(xiàn),該函數(shù)的作用是從傳入的StringList
中獲取數(shù)據(jù),并將數(shù)據(jù)初始化到TableView
模型中,實(shí)現(xiàn)代碼如下。
void MainWindow::iniModelFromStringList(QStringList& aFileContent) { int rowCnt=aFileContent.count(); // 文本行數(shù),第1行是標(biāo)題 model->setRowCount(rowCnt-1); // 實(shí)際數(shù)據(jù)行數(shù),要在標(biāo)題上減去1 // 設(shè)置表頭 QString header=aFileContent.at(0); // 第1行是表頭 // 一個或多個空格、TAB等分隔符隔開的字符串、分解為一個StringList // https://www.cnblogs.com/lyshark QStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts); model->setHorizontalHeaderLabels(headerList); // 設(shè)置表頭文字 // 設(shè)置表格中的數(shù)據(jù) int x = 0,y = 0; QStandardItem *Item; // 有多少列數(shù)據(jù)就循環(huán)多少次 // https://www.cnblogs.com/lyshark for(x=1; x < rowCnt; x++) { QString LineText = aFileContent.at(x); // 獲取數(shù)據(jù)區(qū)的一行 // 一個或多個空格、TAB等分隔符隔開的字符串、分解為一個StringList QStringList tmpList=LineText.split(QRegExp("\\s+"),QString::SkipEmptyParts); // 循環(huán)列數(shù),也就是循環(huán)FixedColumnCount,其中tmpList中的內(nèi)容也是. for(y=0; y < FixedColumnCount-1; y++) { Item = new QStandardItem(tmpList.at(y)); // 創(chuàng)建item model->setItem(x-1,y,Item); // 為模型的某個行列位置設(shè)置Item } // 最后一個數(shù)據(jù)需要取出來判斷,并單獨(dú)設(shè)置狀態(tài) Item=new QStandardItem(headerList.at(y)); // 最后一列是Checkable,需要設(shè)置 Item->setCheckable(true); // 設(shè)置為Checkable // 判斷最后一個數(shù)值是否為0 if (tmpList.at(y) == "0") Item->setCheckState(Qt::Unchecked); // 根據(jù)數(shù)據(jù)設(shè)置check狀態(tài) else Item->setCheckState(Qt::Checked); model->setItem(x-1,y,Item); //為模型的某個行列位置設(shè)置Item } }
初始化組件后效果如下:
實(shí)現(xiàn)添加一行數(shù)據(jù): 為TableView添加一行數(shù)據(jù),在文件末尾插入。
void MainWindow::on_actionAppend_triggered() { QList<QStandardItem *> ItemList; // 創(chuàng)建臨時容器 QStandardItem *Item; // 模擬添加一列的數(shù)據(jù) for(int x=0; x<FixedColumnCount-1; x++) { Item = new QStandardItem("測試(追加行)"); // 循環(huán)創(chuàng)建每一列 ItemList << Item; // 添加到鏈表中 } // 創(chuàng)建最后一個列元素,由于是選擇框所以需要單獨(dú)創(chuàng)建 // https://www.cnblogs.com/lyshark // 1.獲取到最后一列的表頭下標(biāo),最后下標(biāo)為6 QString str = model->headerData(model->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString(); Item=new QStandardItem(str); // 創(chuàng)建 "是否合格" 字段 Item->setCheckable(true); // 設(shè)置狀態(tài)為真 ItemList << Item; // 最后一個選項追加進(jìn)去 model->insertRow(model->rowCount(),ItemList); // 插入一行,需要每個Cell的Item QModelIndex curIndex=model->index(model->rowCount()-1,0); // 創(chuàng)建最后一行的ModelIndex selection->clearSelection(); // 清空當(dāng)前選中項 selection->setCurrentIndex(curIndex,QItemSelectionModel::Select); // 設(shè)置當(dāng)前選中項為當(dāng)前選擇行 }
插入代碼演示效果:
實(shí)現(xiàn)插入一行數(shù)據(jù): 為TableView插入一行數(shù)據(jù)(在文件任意位置插入數(shù)據(jù))
// https://www.cnblogs.com/lyshark void MainWindow::on_actionInsert_triggered() { QList<QStandardItem*> ItemList; // QStandardItem的列表類 QStandardItem *Item; // 模擬插入前五列數(shù)據(jù) for(int i=0;i<FixedColumnCount-1;i++) { Item= new QStandardItem("測試(插入行)"); // 新建一個QStandardItem ItemList << Item; // 添加到列表類 } QString str; // 獲取表頭文字 str=model->headerData(model->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString(); Item=new QStandardItem(str); // 創(chuàng)建Item Item->setCheckable(true); // 設(shè)置為可使用CheckBox ItemList<<Item; // 添加到列表類 QModelIndex curIndex=selection->currentIndex(); // 獲取當(dāng)前選中項的索引 model->insertRow(curIndex.row(),ItemList); // 在當(dāng)前行的前面插入一行 selection->clearSelection(); // 清除當(dāng)前選中項 selection->setCurrentIndex(curIndex,QItemSelectionModel::Select); // 設(shè)置當(dāng)前選中項為當(dāng)前選擇行 }
插入代碼演示效果:
實(shí)現(xiàn)刪除一行數(shù)據(jù): 刪除數(shù)據(jù)之前需要通過selection->currentIndex()
確定當(dāng)前選中行,并通過model->removeRow()
移除即可。
// https://www.cnblogs.com/lyshark void MainWindow::on_actionDelete_triggered() { QModelIndex curIndex = selection->currentIndex(); // 獲取當(dāng)前選擇單元格的模型索引 // 先判斷是不是最后一行 if (curIndex.row()==model->rowCount()-1) { model->removeRow(curIndex.row()); //刪除最后一行 } else { model->removeRow(curIndex.row());//刪除一行,并重新設(shè)置當(dāng)前選擇行 selection->setCurrentIndex(curIndex,QItemSelectionModel::Select); } }
刪除代碼效果演示:
實(shí)現(xiàn)字體數(shù)據(jù)對齊: 表格中的字體可以實(shí)現(xiàn)多種對其方式,對齊方式分為 居中對齊,左對齊,右對齊 三種。
// 設(shè)置表格居中對齊 void MainWindow::on_pushButton_clicked() { if (!selection->hasSelection()) return; QModelIndexList selectedIndex=selection->selectedIndexes(); QModelIndex Index; QStandardItem *Item; for (int i=0; i<selectedIndex.count(); i++) { Index=selectedIndex.at(i); Item=model->itemFromIndex(Index); Item->setTextAlignment(Qt::AlignHCenter); } } // 設(shè)置表格左對齊 // https://www.cnblogs.com/lyshark void MainWindow::on_pushButton_2_clicked() { if (!selection->hasSelection()) //沒有選擇的項 return; //獲取選擇的單元格的模型索引列表,可以是多選 QModelIndexList selectedIndex=selection->selectedIndexes(); for (int i=0;i<selectedIndex.count();i++) { QModelIndex aIndex=selectedIndex.at(i); //獲取其中的一個模型索引 QStandardItem* aItem=model->itemFromIndex(aIndex);//獲取一個單元格的項數(shù)據(jù)對象 aItem->setTextAlignment(Qt::AlignLeft);//設(shè)置文字對齊方式 } } // 設(shè)置表格右對齊 void MainWindow::on_pushButton_3_clicked() { if (!selection->hasSelection()) return; QModelIndexList selectedIndex=selection->selectedIndexes(); QModelIndex aIndex; QStandardItem *aItem; for (int i=0;i<selectedIndex.count();i++) { aIndex=selectedIndex.at(i); aItem=model->itemFromIndex(aIndex); aItem->setTextAlignment(Qt::AlignRight); } }
對齊代碼效果演示:
實(shí)現(xiàn)字體數(shù)據(jù)加粗: 將選中行的字體進(jìn)行加粗顯示。
// 設(shè)置字體加粗顯示 // https://www.cnblogs.com/lyshark void MainWindow::on_pushButton_4_clicked() { if (!selection->hasSelection()) return; //獲取選擇單元格的模型索引列表 QModelIndexList selectedIndex=selection->selectedIndexes(); for (int i=0;i<selectedIndex.count();i++) { QModelIndex aIndex=selectedIndex.at(i); //獲取一個模型索引 QStandardItem* aItem=model->itemFromIndex(aIndex);//獲取項數(shù)據(jù) QFont font=aItem->font(); //獲取字體 font.setBold(true); //設(shè)置字體是否粗體 aItem->setFont(font); //重新設(shè)置字體 }
加粗代碼效果演示:
實(shí)現(xiàn)保存文件: 當(dāng)保存文件被點(diǎn)擊后觸發(fā),通過便利TableWidget模型組件中的數(shù)據(jù),并將數(shù)據(jù)通過aStream << str << "\n";
寫出到記事本中。
// https://www.cnblogs.com/lyshark // 【保存文件】 void MainWindow::on_actionSave_triggered() { QString curPath=QCoreApplication::applicationDirPath(); // 獲取應(yīng)用程序的路徑 // 調(diào)用打開文件對話框選擇一個文件 QString aFileName=QFileDialog::getSaveFileName(this,tr("選擇一個文件"),curPath,"數(shù)據(jù)文件(*.txt);;所有文件(*.*)"); if (aFileName.isEmpty()) // 未選擇文件則直接退出 return; QFile aFile(aFileName); // 以讀寫、覆蓋原有內(nèi)容方式打開文件 if (!(aFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate))) return; QTextStream aStream(&aFile); // 用文本流讀取文件 QStandardItem *Item; QString str; int x = 0,y = 0; ui->plainTextEdit->clear(); // 獲取表頭文字 for (x=0; x<model->columnCount(); x++) { Item=model->horizontalHeaderItem(x); // 獲取表頭的項數(shù)據(jù) str= str + Item->text() + "\t\t"; // 以TAB制表符隔開 } aStream << str << "\n"; // 文件里需要加入換行符\n ui->plainTextEdit->appendPlainText(str); // 獲取數(shù)據(jù)區(qū)文字 for ( x=0; x < model->rowCount(); x++) { str = ""; for( y=0; y < model->columnCount()-1; y++) { Item=model->item(x,y); str=str + Item->text() + QString::asprintf("\t\t"); } // 對最后一列需要轉(zhuǎn)換一下,如果判斷為選中則寫1否則寫0 Item=model->item(x,y); if (Item->checkState()==Qt::Checked) str= str + "1"; else str= str + "0"; ui->plainTextEdit->appendPlainText(str); aStream << str << "\n"; } } // 【導(dǎo)出Txt文件】:將TableView中的數(shù)據(jù)導(dǎo)出到PlainTextEdit顯示 void MainWindow::on_actionView_triggered() { ui->plainTextEdit->clear(); QStandardItem *Item; QString str; //獲取表頭文字 int x=0,y=0; for (x=0; x<model->columnCount(); x++) { // Item=model->horizontalHeaderItem(x); str= str + Item->text() + "\t"; } ui->plainTextEdit->appendPlainText(str); //獲取數(shù)據(jù)區(qū)的每行 for (x=0; x<model->rowCount(); x++) { str=""; for(y=0; y<model->columnCount()-1; y++) { Item=model->item(x,y); str= str + Item->text() + QString::asprintf("\t"); } Item=model->item(x,y); if (Item->checkState()==Qt::Checked) str= str + "1"; else str= str + "0"; ui->plainTextEdit->appendPlainText(str); } }
文件保存后如下:
原文鏈接:https://www.cnblogs.com/LyShark/p/15637813.html
相關(guān)推薦
- 2023-04-04 iOS數(shù)據(jù)持久化UserDefaults封裝器使用詳解_IOS
- 2022-11-04 react-router-dom?v6?使用詳細(xì)示例_React
- 2023-01-14 GoLang并發(fā)機(jī)制探究goroutine原理詳細(xì)講解_Golang
- 2022-12-21 k8s安裝CICD?devtron過程詳解_云其它
- 2022-11-20 解析在Tomcat中啟用虛擬線程特性_Tomcat
- 2022-08-28 PostgreSQL常用字符串分割函數(shù)整理匯總_PostgreSQL
- 2022-03-01 show-overflow-tooltip實(shí)現(xiàn)表格列內(nèi)容過長顯示提示
- 2022-03-30 C語言中static和auto用法詳解_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支