qstandarditemmodel 是標(biāo)準(zhǔn)的以項(xiàng)數(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ù)庫(kù)中較多,例如模型結(jié)構(gòu)負(fù)責(zé)讀取或?qū)懭霐?shù)據(jù)庫(kù),視圖結(jié)構(gòu)則負(fù)責(zé)展示數(shù)據(jù),其條理清晰,編寫代碼便于維護(hù)。
qstandarditemmodel組件通常會(huì)配合tableview
組件一起使用,當(dāng)數(shù)據(jù)庫(kù)或文本中的記錄發(fā)生變化時(shí)會(huì)自動(dòng)同步到組件中,首先繪制ui界面。
其次綁定頂部toolbar
菜單,分別對(duì)菜單增加對(duì)應(yīng)的功能屬性的描述等。
初始化構(gòu)造函數(shù): 當(dāng)程序運(yùn)行時(shí),我們需要對(duì)頁面中的控件逐一初始化,并將table表格與模型通過調(diào)用ui->tableview->setmodel(model)
進(jìn)行綁定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#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選項(xiàng),只保留打開 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)前單元格變化時(shí)的信號(hào)與槽 connect(selection, signal (currentchanged(qmodelindex,qmodelindex)), this ,slot(on_currentchanged(qmodelindex,qmodelindex))); } mainwindow::~mainwindow() { delete ui; } |
初始化時(shí)同時(shí)需要綁定一個(gè)on_currentchanged(qmodelindex,qmodelindex)
信號(hào),當(dāng)用戶選中指定單元格時(shí)相應(yīng)用戶。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 選擇單元格變化時(shí)的響應(yīng),通過在構(gòu)造函數(shù)中綁定信號(hào)和槽函數(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())); //顯示模型索引的行和列號(hào) qstandarditem *aitem; aitem=model->itemfromindex(current); //從模型索引獲得item this ->labcelltext->settext( "單元格內(nèi)容:" +aitem->text()); //顯示item的文字內(nèi)容 } } |
當(dāng)頁面被初始化時(shí),默認(rèn)界面如下:
打開并填充組件: 當(dāng)工具欄中打開文件被點(diǎn)擊后則觸發(fā),打開文件時(shí)通過afile.open
打開,循環(huán)讀入文件,并將文件中的內(nèi)容逐行追加到qstringlist ffilecontent
中,當(dāng)追加完畢后,直接調(diào)用inimodelfromstringlist(ffilecontent);
完成對(duì)頁面tableview組件的初始化,并設(shè)置其他控件狀態(tài)為可點(diǎn)擊。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
void mainwindow::on_actionopen_triggered() { qstring curpath=qcoreapplication::applicationdirpath(); // 獲取應(yīng)用程序的路徑 // 調(diào)用打開文件對(duì)話框打開一個(gè)文件 // https://www.cnblogs.com/lyshark qstring afilename=qfiledialog::getopenfilename( this , "打開一個(gè)文件" ,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)代碼如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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行是表頭 // 一個(gè)或多個(gè)空格、tab等分隔符隔開的字符串、分解為一個(gè)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ū)的一行 // 一個(gè)或多個(gè)空格、tab等分隔符隔開的字符串、分解為一個(gè)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); // 為模型的某個(gè)行列位置設(shè)置item } // 最后一個(gè)數(shù)據(jù)需要取出來判斷,并單獨(dú)設(shè)置狀態(tài) item= new qstandarditem(headerlist.at(y)); // 最后一列是checkable,需要設(shè)置 item->setcheckable( true ); // 設(shè)置為checkable // 判斷最后一個(gè)數(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); //為模型的某個(gè)行列位置設(shè)置item } } |
初始化組件后效果如下:
實(shí)現(xiàn)添加一行數(shù)據(jù): 為tableview添加一行數(shù)據(jù),在文件末尾插入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
void mainwindow::on_actionappend_triggered() { qlist<qstandarditem *> itemlist; // 創(chuàng)建臨時(shí)容器 qstandarditem *item; // 模擬添加一列的數(shù)據(jù) for ( int x=0; x<fixedcolumncount-1; x++) { item = new qstandarditem( "測(cè)試(追加行)" ); // 循環(huán)創(chuàng)建每一列 itemlist << item; // 添加到鏈表中 } // 創(chuàng)建最后一個(gè)列元素,由于是選擇框所以需要單獨(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; // 最后一個(gè)選項(xiàng)追加進(jìn)去 model->insertrow(model->rowcount(),itemlist); // 插入一行,需要每個(gè)cell的item qmodelindex curindex=model->index(model->rowcount()-1,0); // 創(chuàng)建最后一行的modelindex selection->clearselection(); // 清空當(dāng)前選中項(xiàng) selection->setcurrentindex(curindex,qitemselectionmodel::select); // 設(shè)置當(dāng)前選中項(xiàng)為當(dāng)前選擇行 } |
插入代碼演示效果:
實(shí)現(xiàn)插入一行數(shù)據(jù): 為tableview插入一行數(shù)據(jù)(在文件任意位置插入數(shù)據(jù))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// 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( "測(cè)試(插入行)" ); // 新建一個(gè)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)前選中項(xiàng)的索引 model->insertrow(curindex.row(),itemlist); // 在當(dāng)前行的前面插入一行 selection->clearselection(); // 清除當(dāng)前選中項(xiàng) selection->setcurrentindex(curindex,qitemselectionmodel::select); // 設(shè)置當(dāng)前選中項(xiàng)為當(dāng)前選擇行 } |
插入代碼演示效果:
實(shí)現(xiàn)刪除一行數(shù)據(jù): 刪除數(shù)據(jù)之前需要通過selection->currentindex()
確定當(dāng)前選中行,并通過model->removerow()
移除即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 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); } }<br> |
刪除代碼效果演示:
實(shí)現(xiàn)字體數(shù)據(jù)對(duì)齊: 表格中的字體可以實(shí)現(xiàn)多種對(duì)其方式,對(duì)齊方式分為 居中對(duì)齊,左對(duì)齊,右對(duì)齊 三種。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
// 設(shè)置表格居中對(duì)齊 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è)置表格左對(duì)齊 // https://www.cnblogs.com/lyshark void mainwindow::on_pushbutton_2_clicked() { if (!selection->hasselection()) //沒有選擇的項(xiàng) return ; //獲取選擇的單元格的模型索引列表,可以是多選 qmodelindexlist selectedindex=selection->selectedindexes(); for ( int i=0;i<selectedindex.count();i++) { qmodelindex aindex=selectedindex.at(i); //獲取其中的一個(gè)模型索引 qstandarditem* aitem=model->itemfromindex(aindex); //獲取一個(gè)單元格的項(xiàng)數(shù)據(jù)對(duì)象 aitem->settextalignment(qt::alignleft); //設(shè)置文字對(duì)齊方式 } } // 設(shè)置表格右對(duì)齊 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); } } |
對(duì)齊代碼效果演示:
實(shí)現(xiàn)字體數(shù)據(jù)加粗: 將選中行的字體進(jìn)行加粗顯示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// 設(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); //獲取一個(gè)模型索引 qstandarditem* aitem=model->itemfromindex(aindex); //獲取項(xiàng)數(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";
寫出到記事本中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
// https://www.cnblogs.com/lyshark // 【保存文件】 void mainwindow::on_actionsave_triggered() { qstring curpath=qcoreapplication::applicationdirpath(); // 獲取應(yīng)用程序的路徑 // 調(diào)用打開文件對(duì)話框選擇一個(gè)文件 qstring afilename=qfiledialog::getsavefilename( this ,tr( "選擇一個(gè)文件" ),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); // 獲取表頭的項(xiàng)數(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" ); } // 對(duì)最后一列需要轉(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); } } |
文件保存后如下:
到此這篇關(guān)于c/c++中的 qt standarditemmodel 數(shù)據(jù)模型應(yīng)用解析的文章就介紹到這了,更多相關(guān)c++ qt standarditemmodel 數(shù)據(jù)模型內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://www.cnblogs.com/LyShark/p/15637813.html