<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Qt6.0開發(fā) 第五章 模型-視圖結(jié)構(gòu)

      第五章 模型-視圖結(jié)構(gòu)


      模型-視圖結(jié)構(gòu)概述

      模型-視圖結(jié)構(gòu)是一種將數(shù)據(jù)存儲(chǔ)和界面分離的編程方法.模型存儲(chǔ)數(shù)據(jù),視圖組件顯示模型中的數(shù)據(jù),在視圖組件里修改的數(shù)據(jù)會(huì)被自動(dòng)保存到模型里.

      GUI程序的主要功能是可由用戶在界面上編輯和修改數(shù)據(jù),典型的如數(shù)據(jù)庫應(yīng)用程序.在數(shù)據(jù)庫應(yīng)用程序中,界面上的數(shù)據(jù)來源于數(shù)據(jù)庫,用戶在界面上修改數(shù)據(jù),修改后的數(shù)據(jù)又保存到數(shù)據(jù)庫.

      模型-視圖的基本結(jié)構(gòu)包括以下幾個(gè)部分:

      • 源數(shù)據(jù)(data):原始數(shù)據(jù),如數(shù)據(jù)庫的一個(gè)數(shù)據(jù)表或SQL查詢結(jié)果等
      • 視圖(view):也稱視圖組件,是界面組件,視圖從模型獲得數(shù)據(jù)然后將其顯示在界面上.
      • 模型(model):也稱數(shù)據(jù)模型,與源數(shù)據(jù)通信,并為視圖組件提供數(shù)據(jù)接口.它從源數(shù)據(jù)提取需要的數(shù)據(jù),用于視圖組件進(jìn)行顯示和編輯.
      • 代理(delegate):為視圖與模型之間交互操作提供臨時(shí)的編輯器.模型向視圖提供數(shù)據(jù)一般是單向的,一般僅用于顯示.當(dāng)需要在視圖上編輯數(shù)據(jù)時(shí),代理會(huì)為編輯數(shù)據(jù)提供一個(gè)編輯器.

      模型

      所有基于項(xiàng)(item)的模型類都是基于QAbstractItemModel類的,這個(gè)類定義了試圖組件和代理存取數(shù)據(jù)的接口.

      模型只是在內(nèi)存中臨時(shí)存儲(chǔ)數(shù)據(jù),模型的數(shù)據(jù)來源可以是其他類,文件,數(shù)據(jù)庫或任何數(shù)據(jù)源.

      模型類繼承關(guān)系:

      • QAbstractItemModel:抽象模型類父類
        • QFileSystemModel:用于表示計(jì)算機(jī)上文件系統(tǒng)的模型類
        • QAbstractListModel:抽象列表類
          • QStringListModel:用于表示字符串列表數(shù)據(jù)的模型類
        • QStandardItemModel:標(biāo)準(zhǔn)的基于項(xiàng)的模型類,每個(gè)項(xiàng)都為QStandardItem對(duì)象
        • QAbstractTableModel:抽象表類
          • QSqlQueryModel:用于表示數(shù)據(jù)庫SQL查詢結(jié)果的模型類
            • QSqlTableModel:用于表示數(shù)據(jù)庫的一個(gè)數(shù)據(jù)表的模型類

      視圖

      視圖就是用于顯示模型中的數(shù)據(jù)的界面組件,Qt提供的視圖組件主要有以下幾個(gè):

      • QListView:用于顯示單列的列表結(jié)構(gòu),適用于一維數(shù)據(jù)
      • QTreeView:用于顯示樹狀結(jié)構(gòu)的數(shù)據(jù),適用于樹狀結(jié)構(gòu)數(shù)據(jù)的操作
      • QTableView:用于顯示表格數(shù)據(jù),適用于二維表格數(shù)據(jù)的操作
      • QColumnView:用多個(gè)QListView顯示樹狀結(jié)構(gòu)數(shù)據(jù),樹狀結(jié)構(gòu)的一層用一個(gè)QListView顯示
      • QUndoView:用于顯示undo指令棧內(nèi)數(shù)據(jù)的視圖組件,是QListView的子類

      只需調(diào)用視圖類的setModel()函數(shù)為視圖組件設(shè)置一個(gè)模型,模型的數(shù)據(jù)就可以顯示在視圖組件上.在視圖組件上修改數(shù)據(jù)后,數(shù)據(jù)可以自動(dòng)保存到模型.

      視圖組件的數(shù)據(jù)來源于模型,視圖組件不存儲(chǔ)數(shù)據(jù).便利類則為組件的每個(gè)節(jié)點(diǎn)或單元格創(chuàng)建一個(gè)項(xiàng),用項(xiàng)存儲(chǔ)數(shù)據(jù).

      因此,便利類缺乏對(duì)大型數(shù)據(jù)源進(jìn)行靈活處理的能力,只適用于小型數(shù)據(jù)的顯示和編輯,而視圖組件則會(huì)根據(jù)模型的數(shù)據(jù)內(nèi)容自動(dòng)顯示.

      代理

      代理能夠在視圖組件上為編輯數(shù)據(jù)提供臨時(shí)的編輯器.代理負(fù)責(zé)從模型獲取相應(yīng)的數(shù)據(jù),然后將其顯示在編輯器里,修改數(shù)據(jù)又將編輯器里的數(shù)據(jù)保存到模型中.

      QAbstractItemDelegate是所有代理類的基類,作為抽象類,它不能直接用于創(chuàng)建對(duì)象.它有兩個(gè)子類,即QItemDelegate和QStyledItemDelegate,這兩個(gè)類基本相同,而QStyledItemDelegate能使用Qt樣式表定義的當(dāng)前樣式繪制代理組件.

      對(duì)于一些特殊的數(shù)據(jù)編輯需求,則可以從QStyledItemDelegate中繼承.

      一些基本概念

      在模型-視圖結(jié)構(gòu)中,模型為視圖組件和代理提供存取數(shù)據(jù)的標(biāo)準(zhǔn)接口.

      QAbstractItemModel是所有模型類的基類,不管底層的數(shù)據(jù)結(jié)構(gòu)是如何組織數(shù)據(jù)的,QAbstractItemModel的子類都以表格的層次結(jié)構(gòu)展示數(shù)據(jù),視圖組件按照這種規(guī)則規(guī)則來存取模型中的數(shù)據(jù),但是展示給用戶的形式不一樣.

      模型的三種常見展示形式:

      • 列表模型(list model)
      • 表格模型(table model)
      • 樹狀模型(tree model)

      不管模型的表現(xiàn)形式是怎樣的,模型中存儲(chǔ)數(shù)據(jù)的基本單元都是項(xiàng)(item),每個(gè)項(xiàng)有一個(gè)行號(hào)和一個(gè)列號(hào),還有一個(gè)父項(xiàng)(parent item).三個(gè)模型都有一個(gè)隱藏的根項(xiàng)(item).

      為了確保數(shù)據(jù)的展示與數(shù)據(jù)存取方式分離,模型中引入了模型索引(model index)的概念.通過模型索引,視圖組件和代理都通過模型索引來獲取數(shù)據(jù).

      QModelIndex是表示模型索引的類.模型索引提供訪問數(shù)據(jù)的臨時(shí)指針,用于通過模型提取或修改數(shù)據(jù).

      因?yàn)槟P蛢?nèi)部組織數(shù)據(jù)的結(jié)構(gòu)可能隨時(shí)改變,所以模型索引是臨時(shí)的.

      模型的基本形式是用行和列定義的表格數(shù)據(jù),但這并不意味著底層的數(shù)據(jù)是用二維數(shù)據(jù)存儲(chǔ)的,是用行與列只是為了組件之間交互方便.一個(gè)模型索引包含行號(hào)與列號(hào).

      在創(chuàng)建模型索引的函數(shù)中需要傳遞行號(hào),列號(hào)和父項(xiàng)的模型索引.

      當(dāng)模型為列表或表格結(jié)構(gòu)時(shí),是用行號(hào)、列號(hào)訪問數(shù)據(jù)比較直觀,所有項(xiàng)的父項(xiàng)就是頂層項(xiàng).

      當(dāng)模型為樹狀結(jié)構(gòu)時(shí)情況比較復(fù)雜,一個(gè)節(jié)點(diǎn)有父節(jié)點(diǎn),其他可以是其他節(jié)點(diǎn)的父節(jié)點(diǎn),在構(gòu)造節(jié)點(diǎn)的模型索引時(shí),需要指定正確的行號(hào),列號(hào)和父節(jié)點(diǎn).

      在為模型的一個(gè)項(xiàng)設(shè)置數(shù)據(jù)時(shí),可以為項(xiàng)設(shè)置不同的角色數(shù)據(jù).QAbstractItemModel定義了設(shè)置項(xiàng)的數(shù)據(jù)的函數(shù)setData():

      • bool QAbstractItemModel:::setData(const QModelIndex& index,const
        QVariant &value,int role =Qt::EditRole)

      其中,index是項(xiàng)的模型索引,value是需要設(shè)置的數(shù)據(jù),role是設(shè)置數(shù)據(jù)的角色.

      可以為一個(gè)項(xiàng)設(shè)置不同角色的數(shù)據(jù),角色參數(shù)role用枚舉類型Qt::ItemDataRole的枚舉類型表示.枚舉類型Qt::ItemDataRole常用的一些枚舉值及其含義如表所示,表中的橘色數(shù)據(jù)類型用于相應(yīng)數(shù)據(jù)的數(shù)據(jù)的類型:

      • bool QAbstractItemModel::setData(const QModelIndex &index,const QVariant &value,int role=Qt::EditRole)
      枚舉類型Qt::ItemDataRole常用的一些枚舉值
      枚舉值 角色數(shù)據(jù)類型 含義
      Qt::DisplayRole QString 界面上顯示的字符串
      Qt::DecorationRole QIcon,QColor 在界面上期裝飾作用的數(shù)據(jù)
      Qt::EditRole QString 界面上適合在編輯器中顯示的數(shù)據(jù)
      Qt::ToolTipRole QString 項(xiàng)的toolTip
      Qt::StatusTipRole QString 項(xiàng)的statusTip
      Qt::FontRole QFont 項(xiàng)的字體
      Qt::TextAlignmentRole Qt::Alignment 項(xiàng)的對(duì)齊方式
      Qt::BackgroundRole QBrush 項(xiàng)的背景色
      Qt::ForegroundRole QBrush 項(xiàng)的前景色
      Qt::CheckStateRole Qt::CheckState 項(xiàng)的復(fù)選狀態(tài)
      Qt::UserRole QVariant 自定義的用戶數(shù)據(jù)

      在獲取一個(gè)項(xiàng)的數(shù)據(jù)時(shí)也需要指定角色,以獲取不同角色的數(shù)據(jù).QAbstractItemModel定義了函數(shù)data()可以返回一個(gè)項(xiàng)的不同角色的數(shù)據(jù).

      • QVariant QAbstractItemModel::data(const QModelIndex &index,int role=Qt::DisplayRole)

      通過為一個(gè)項(xiàng)的不同角色定義數(shù)據(jù),可以告知試圖組件和代理如何展示數(shù)據(jù).

      QAbstractItemModel類

      QAbstractItemModel是所有模型類的字節(jié)或間接父類,它定義了模型的通用接口函數(shù),作為抽象類不能直接用來創(chuàng)建對(duì)象實(shí)例.

      由于QAbstractItemModel是抽象類,所以它的很多函數(shù)都是虛函數(shù).

      下面給出一些關(guān)于QAbstractItemModel的接口函數(shù):

      • int rowCount(const QModelIndex &parent=QModelIndex())//返回行數(shù)
      • int columnCount(const QModelIndex &parent=QModelIndex())//返回列數(shù)
      • bool insertRow(int row,const QModelIndex &parent=QModelIndex())//插入行
      • bool insertRows(int row,int count,const QModelIndex &parent=QModelIndex())//插入多行
      • bool removeRow(int row,const QModelIndex &parent=QModelIndex())//移除行
      • bool removeRows(int row,int count,const QModelIndex &parent=QModelIndex())//移除多行
      • bool insertColumn(int column,const QModelIndex &parent=QModelIndex())//插入列
      • bool insertColumns(int column,int count,const QModelIndex &parent=QModelIndex())//插入多列
      • bool removeColumn(int column,const QModelIndex &parent=QModelIndex())//移除列
      • bool removeColumns(int column,int count,const QModelIndex &parent=QModelIndex())//移除多列
      • bool moveRow(const QModelIndex &sourceParent,int sourceRow,const QModelIndex &destinationParent,int destinationChild)//移動(dòng)行
      • bool moveColumn(const QModelIndex &sourceParent,int sourceColumn,const QModelIndex &destinationParent,int destinationChild)//移動(dòng)列
      • void sort(int column,Qt::SortOrder order=Qt::AscendingOrder)//排序項(xiàng)
      • bool setData(const QModelIndex &index,const QVariant &value,int role=Qt::EditRole)//設(shè)置數(shù)據(jù)
      • QVariant data(const QModelIndex &index,int role=Qt::EditRole)//返回?cái)?shù)據(jù)
      • bool clearItemData(const QModelIndex &index)//清楚項(xiàng)的數(shù)據(jù)

      QAbstractItemView類

      QAbstractView類是所有視圖組件類的父類,它定義了視圖組件類共有的一些接口.

      下面是其常用的一些函數(shù):

      • void setModel(QAbstractItemModel *model)//設(shè)置數(shù)據(jù)模型
      • QAbstractItemModel *model()//返回關(guān)聯(lián)模型的數(shù)據(jù)對(duì)象指針
      • void setSelectionModel(QItemSelectionModel *selectionModel)//設(shè)置選擇模型
      • QItemSelectionModel *selectionModel()//返回選擇模型的對(duì)象指針
      • QModelIndex currentIndex()//返回當(dāng)前項(xiàng)的模型索引
      • void setCurrentIndex(const QModelIndex &index)//設(shè)置模型索引為index的項(xiàng)為當(dāng)前項(xiàng)
      • void selectAll()//選擇視圖中的所有項(xiàng)
      • void clearSelection()//清除所有選擇

      下面是一些常用的屬性:

      • editTriggers屬性:表示視圖組件是否可以編輯數(shù)據(jù)以及進(jìn)入編輯狀態(tài)的方式等.
        • 常用函數(shù)有:
          • void setEditTriggers(QAbstractItemView::EditTriggers triggers)//
          • QAbstractItemView::EditTriggers editTriggers()
        • QAbstractItemView::EditTriggers的值有:
          • NoEditTriggers:不允許編輯
          • CurrentChanged:當(dāng)前項(xiàng)變化時(shí)進(jìn)入編輯狀態(tài)
          • DoubleClicked:點(diǎn)擊一個(gè)已選擇的項(xiàng)時(shí)進(jìn)入編輯狀態(tài)
          • SelectedClicked:點(diǎn)擊一個(gè)已選擇的項(xiàng)時(shí)進(jìn)入編輯狀態(tài)
          • EditKeyPressed:當(dāng)平臺(tái)的編輯按鍵被按下時(shí)進(jìn)入編輯狀態(tài)
          • AnyKeyPressed:任何鍵被按下時(shí)進(jìn)入編輯狀態(tài)
          • AllEditTriggers:發(fā)生以上任何動(dòng)作時(shí)進(jìn)入編輯狀態(tài)
      • alternatingRowColors屬性:這個(gè)屬性設(shè)置各行是否需要交替使用不同背景色.
      • selectionMode屬性:這個(gè)屬性表示在視圖組件上選擇項(xiàng)的操作模式,該屬性值一般為SelectionMode類型
        • QAbstractItemView::SelectionMode的值有:
          • SingleSelection:單選
          • ContiguousSelection:連續(xù)選擇,如按住shift
          • ExtendedSelection:擴(kuò)展選擇,如按住ctrl
          • MultiSelection:多選
          • NoSelection:不允許選擇
      • selectionBehavior屬性:這個(gè)屬性表示點(diǎn)擊鼠標(biāo)時(shí)操作的行為,屬性值為SelectionBehavior類型.
        • QAbstractItemView::SelectionBehavior的值有:
          • SelectItems:選擇單個(gè)項(xiàng)
          • SelectRows:選擇行,點(diǎn)擊單個(gè)單元格選擇對(duì)應(yīng)行
          • SelectColumns:選擇列,點(diǎn)擊單個(gè)單元格選擇對(duì)應(yīng)列

      QAbstractItemView常用的信號(hào)有:

      • void clicked(const QModelIndex &index)//點(diǎn)擊某個(gè)項(xiàng)時(shí)
      • void doubleClicked(const QModelIndex &index)//雙擊某個(gè)項(xiàng)時(shí)
      • void entered(const QModelIndex &index)//鼠標(biāo)移動(dòng)到某個(gè)項(xiàng)時(shí)
      • void pressed(const QModelIndex &index)//鼠標(biāo)單擊某個(gè)項(xiàng)時(shí)

      QStringListModel和QListView

      QStringListModel是處理字符串列表的模型類,其實(shí)例可以作為QListView組件的數(shù)據(jù)模型.

      QStringListModel內(nèi)部存儲(chǔ)了一個(gè)字符串列表,通過字符串列表內(nèi)容自動(dòng)顯示在關(guān)聯(lián)容器上.

      QStringListModel類

      QStringListModel類有兩種參數(shù)形式的構(gòu)造函數(shù),定義如下:

      • QStringListModel(const QStringList&strings,QObject *parent=nullptr)
      • QStringListModel(QObject *parent=nullptr)

      作為字符串列表數(shù)據(jù)的模型,QStringListModel對(duì)象內(nèi)部有一個(gè)字符串列表,對(duì)模型數(shù)據(jù)的修改就是對(duì)QStringListModel對(duì)象內(nèi)部字符串的修改.

      QStringListModel繼承于QAbstractItemModel,新增加的函數(shù)只有兩個(gè):

      • void setStringList(const QStringList &strings)//設(shè)置字符串列表
      • QStringList stringList()//返回模型內(nèi)部的字符串列表

      下面給出一個(gè)使用例子用于方便理解:

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          m_list<<"北京"<<"上海"<<"成都"<<"長沙"<<"廣州";
          m_lisModel= new QStringListModel(m_list,this);
          m_lisModel->setStringList(m_list);
          ui->ltvView1->setModel(m_lisModel);
          ui->ltvView1->setEditTriggers(QAbstractItemView::DoubleClicked|
                                        QAbstractItemView::SelectedClicked);
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::on_btnReliveList_clicked()
      {
          m_lisModel->setStringList(m_list);
      }
      
      
      void MainWindow::on_btnClearList_clicked()
      {
          m_lisModel->removeRows(0,m_lisModel->rowCount());
      }
      
      
      void MainWindow::on_chkEditable_clicked(bool checked)
      {
          if(checked)
              ui->ltvView1->setEditTriggers(QAbstractItemView::DoubleClicked|
                                            QAbstractItemView::SelectedClicked);
          else
              ui->ltvView1->setEditTriggers(QAbstractItemView::NoEditTriggers);
      }
      
      
      void MainWindow::on_btnAddItem_clicked()
      {
          m_lisModel->insertRow(m_lisModel->rowCount());
          QModelIndex index= m_lisModel->index(m_lisModel->rowCount()-1);
          m_lisModel->setData(index,QString("new item %1").arg(m_lisModel->rowCount()),Qt::DisplayRole);
          ui->ltvView1->setCurrentIndex(index);
      }
      
      
      void MainWindow::on_btnInsertItem_clicked()
      {
          QModelIndex index= ui->ltvView1->currentIndex();
          m_lisModel->insertRow(index.row());
          m_lisModel->setData(index,QString("new item %1").arg(index.row()),Qt::DisplayRole);
          ui->ltvView1->setCurrentIndex(index);
      }
      
      
      void MainWindow::on_btnDeleteItem_clicked()
      {
          QModelIndex index= ui->ltvView1->currentIndex();
          m_lisModel->removeRow(index.row());
      }
      
      
      void MainWindow::on_btnUpper_clicked()
      {
          QModelIndex index;
          int curRow= ui->ltvView1->currentIndex().row();
          m_lisModel->moveRow(index,curRow,index,curRow-1);
      }
      
      
      void MainWindow::on_btnLower_clicked()
      {
          QModelIndex index;
          int curRow= ui->ltvView1->currentIndex().row();
          m_lisModel->moveRow(index,curRow,index,curRow+2);
      }
      
      
      void MainWindow::on_btnSort_clicked(bool checked)
      {
          if(checked)
              m_lisModel->sort(Qt::AscendingOrder);
          else
              m_lisModel->sort(Qt::DescendingOrder);
      }
      
      
      void MainWindow::on_btnClearPlt_clicked()
      {
          ui->pltEdit->clear();
      }
      
      
      void MainWindow::on_btnShowSL_clicked()
      {
          QStringList tempList= m_lisModel->stringList();
          ui->pltEdit->clear();
          for(auto iter:tempList)
              ui->pltEdit->appendPlainText(iter);
      }
      

      QStanardItemModel和QTableView

      QStandardItemModel是基于項(xiàng)的模型類,每個(gè)項(xiàng)是一個(gè)QStandardItem對(duì)象,可以存儲(chǔ)各種數(shù)據(jù).QStandardItemModel通常與QTableView組成模型-視圖結(jié)構(gòu),實(shí)現(xiàn)二維數(shù)據(jù)的管理.

      QTableView類

      QTableView繼承自QAbstractItemView類,其新定義的屬性主要用于控制顯示效果,在UI可視化設(shè)計(jì)時(shí)就可以設(shè)置QTableView組件的各種屬性.

      QTableView組件有水平表頭和垂直表頭,都是QHeaderView對(duì)象,可以設(shè)置和返回表頭對(duì)象.

      相關(guān)函數(shù)定義如下:

      • void QTableView::setHorizontalHeader(QHeaderView *header)//設(shè)置水平表頭
      • void QTableView::setVerticalHeader(QHeaderView *header)//設(shè)置垂直表頭
      • QHeaderView *QTableView::horizontalHeader()//返回水平表頭對(duì)象指針
      • QHeaderView *QTableView::verticalHeaer()//返回垂直表頭對(duì)象指針

      當(dāng)QTableView使用一個(gè)QStandardItemModel對(duì)象作為數(shù)據(jù)模型時(shí),它會(huì)自動(dòng)創(chuàng)建表頭對(duì)象,垂直表頭一般顯示行號(hào),水平表頭一般顯示列的標(biāo)題.

      QStandardItemModel類

      QStandardItemModel是以項(xiàng)為基本數(shù)據(jù)單元的模型類,每個(gè)項(xiàng)是一個(gè)QStandardItem對(duì)象.

      項(xiàng)可以存儲(chǔ)各種角色的數(shù)據(jù),如文字,字體,對(duì)齊方式,圖標(biāo),復(fù)選狀態(tài)等.

      如果以多行多列的二維數(shù)組形式存儲(chǔ)項(xiàng),就是表格模型;如果表格模型只有一列,就是列表模型;如果存儲(chǔ)項(xiàng)時(shí)為項(xiàng)指定父項(xiàng),就構(gòu)成樹狀模型.

      如果一個(gè)QStandardItemModel對(duì)象是表格模型,將它設(shè)置為QTableView組件的數(shù)據(jù)模型后,視圖組件就用表格的形式顯示模型的數(shù)據(jù),并且根據(jù)每個(gè)單元格的項(xiàng)定義各種角色數(shù)據(jù)控制顯示效果.

      QStandardItemModel的接口主要有:

      • void setRowCount(int rows)
      • void setColumnCount(int columns)
      • void setItem(int row,int column,QStandardItem *item)
      • void setItem(int row,QStandardItem *item)
      • QStandardItem *item(int row,int column=0)
      • QStandardItem *itemFromIndex(const QModelIndex &index)
      • QModelIndex indexFromItem(const QStandardItem *item)
      • void appendRow(const QList<QStandardItem *>&items)
      • void appendRow(QStandardItem *item)
      • void appednColumn(cosnt QList<QStandardItem*>&items)
      • void insertRow(int row,const QList<QStandardItem *>&items)
      • void insertRow(int row,QStandardItem *item)
      • bool insertRow(int row,const QModelIndex &parent=QModelIndex())
      • void insertColumn(int column,const QList<QStandardItem *>&items)
      • bool insertColumn(int column,const QModelIndex &parent=QModelIndex())
      • QList<QStandardItem*>takeRow(int row)
      • QList<QStandardItem*>takeColumn(int column)
      • QStandardItem *takeItem(int row,int column=0)
      • void setHorizontalHeaderItem(int column,QStandardItem *item)
      • void setHorizontalHeaderLabels(const QStringList &labels)
      • QStandardItem *horizontalHeaderItem(int column)
      • QStandardItem takeHorizontalHeaderItem(int column)
      • void setVerticalHeaderItem(int row,QStandardItem *item)
      • void setVerticalHeaderLabels(const QStringList &labels)
      • QStandardItem *verticalHeaderItem(int row)
      • QStandardItem *takeVerticalHeaderItem(int row)
      • void clear()

      QStandardItemModel新定義了一個(gè)信號(hào),在任何一個(gè)項(xiàng)的數(shù)據(jù)變化時(shí)該信號(hào)就會(huì)發(fā)射:

      • void itemChanged(QStandardItem *item)

      QStandardItem類

      QStandardItemModel數(shù)據(jù)模型中每個(gè)項(xiàng)都是一個(gè)QStandardItem對(duì)象.QStandardItem對(duì)象存儲(chǔ)了一個(gè)項(xiàng)的各種特性參數(shù),還可以存儲(chǔ)用戶自定義數(shù)據(jù).一個(gè)項(xiàng)可以添加子項(xiàng),子項(xiàng)也是QStandardItem類型的對(duì)象.

      QStandardItem類沒有父類,它存儲(chǔ)項(xiàng)的各種特性內(nèi)容與設(shè)置各種特性.

      QStandardItem的常用接口函數(shù)
      讀取函數(shù) 設(shè)置函數(shù) 設(shè)置函數(shù)的功能
      text() setText() 設(shè)置項(xiàng)的顯示文字
      toolTip() setToolTip() 設(shè)置toolTip文字
      statusTip() setStatusTip() 設(shè)置statusTip文字
      icon() setIcon() 設(shè)置項(xiàng)的圖標(biāo)
      font() setFont() 設(shè)置文字的字體
      textAlignment() setTextAlignment() 設(shè)置文字的對(duì)齊方式
      foreground() setForeground() 設(shè)置項(xiàng)的前景色
      background() setBackground() 設(shè)置項(xiàng)的背景色
      isEnabled() setEnabled() 設(shè)置項(xiàng)是否能夠交互
      isEditable() setEditable() 設(shè)置項(xiàng)是否可以被編輯
      isSelectable() setSelectable() 設(shè)置項(xiàng)是否可以被選擇
      isCheckable() setCheckable() 設(shè)置項(xiàng)是否可以復(fù)選
      checkState() setCheckable() 設(shè)置項(xiàng)的復(fù)選狀態(tài)
      isAutoTristate() setAutoTristate() 設(shè)置是否自動(dòng)改變?nèi)N復(fù)選狀態(tài)
      isUserTristate() setUserTristate() 設(shè)置是否由用戶決定三種復(fù)選狀態(tài)
      flags() setFlags() 設(shè)置項(xiàng)的標(biāo)志
      row() -- 返回自身父項(xiàng)的所有子項(xiàng)的行號(hào)
      column() -- 返回自身父項(xiàng)的所有子項(xiàng)的列號(hào)

      此外,還有一些函數(shù)很重要:

      • void QStandardItem::setFlags(Qt::ItemFlags flags)//設(shè)置標(biāo)志
      • void QStandardItem::setData(const QVariant &value,int role=Qt::UserRole+1)//設(shè)置自定義數(shù)據(jù)
      • QVariant QStandardItem::data(int role=Qt::UserRole+1)//返回用戶自定義數(shù)據(jù)
      • void QStandardItem::clearData()//清除用戶自定義數(shù)據(jù)

      QStandard管理子項(xiàng)的函數(shù)有:

      • void appendRow(const QList<QStandardItem *>&items)
      • void appendRow(QStandardItem *item)
      • void appednColumn(cosnt QList<QStandardItem*>&items)
      • void insertRow(int row,const QList<QStandardItem *>&items)
      • void insertRow(int row,QStandardItem *item)
      • bool insertRow(int row,const QModelIndex &parent=QModelIndex())
      • void insertColumn(int column,const QList<QStandardItem*>&items)
      • void insertColumns(int column,int count)
      • void removeColumn(int column)
      • void removeColumns(int column,int count)
      • int rowCount()
      • int columnCount()
      • bool hasChildren()
      • QStandardItem *child(int row,int column=0)

      如果采用樹狀模型,那么QStandardItemModel管理所有的頂層項(xiàng),而各個(gè)一級(jí)節(jié)點(diǎn)的字節(jié)子節(jié)點(diǎn)則通過QStandardItem類來管理.

      QItemSelectionModel類

      一個(gè)視圖組件需要設(shè)置一個(gè)數(shù)據(jù)模型,還可以設(shè)置一個(gè)選擇模型.QItemSelectionModel是選擇模型類,它的功能是跟蹤視圖組件上的選擇操作,給出選擇范圍.

      為了設(shè)置視圖模型,需要用到函數(shù)setModell()為模型設(shè)置數(shù)據(jù)模型,函數(shù)定義如下:

      • void QItemSelecitonModel::setModel(QAbstractItemModel *model)//為選擇模型設(shè)置數(shù)據(jù)模型

      將數(shù)據(jù)模型,選擇模型,視圖模型這3種對(duì)象做好關(guān)聯(lián)設(shè)置后,在視圖組件上進(jìn)行選擇操作時(shí),選擇模型就可以跟蹤視圖組件上的選擇操作.

      QItemSelectionModel有一些接口函數(shù):

      • bool hasSelection()//是否有被選擇的項(xiàng)
      • QModelIndex currentIndex()//返回當(dāng)前項(xiàng)的模型索引
      • bool isSelected(const QModelIndex &index)//模型索引為index的項(xiàng)是否被選中
      • QModelIndexList selectedIndexes()//返回所有被選擇項(xiàng)的模型索引列表
      • QModelIndexList selectedRows(int column=0)//返回column列所有被選擇項(xiàng)的模型索引列表
      • QModelIndexList selectedColumns(int row=0)//返回row行所有被選擇項(xiàng)的模型索引表
      • void clear()//清除選擇模型
      • void clearCurrentIndex()//清除當(dāng)前索引
      • void clearSelection()//清除所有選擇

      QItemSelectionModel有幾個(gè)信號(hào):

      • void currentChanged(const QModelIndex &current,const QModelIndex &previous)//當(dāng)前項(xiàng)改變
      • void selectionChanged(const QItemSelection &selected,const QItemSelection &deselected)
        //選擇多個(gè)單元格或取消選擇一些單元格

      下面給出一個(gè)綜合使用上述知識(shí)的例子:
      mainWindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QLabel>
      #include <QStandardItemModel>
      #include <QItemSelectionModel>
      #include <QFileDialog>
      #include <QString>
      
      QT_BEGIN_NAMESPACE
      namespace Ui {
      class MainWindow;
      }
      QT_END_NAMESPACE
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui;
          QLabel *labCurFile,*labCellPos,*labCellText;
          const int fixedColum=6;
          QStandardItemModel *m_model;
          QItemSelectionModel *m_selection;
      
          void iniModelData(QStringList &fileContent);
      private slots:
          void do_currentChanged(const QModelIndex&current,const QModelIndex&previous);
          void on_actOpen_triggered();
          void on_actAddRow_triggered();
          void on_actInsertRow_triggered();
          void on_actDeleteRow_triggered();
          void on_actModelData_triggered();
          void on_actAlignLeft_triggered();
          void on_actAlignCenter_triggered();
          void on_actAlignRight_triggered();
          void on_actFontBold_triggered(bool checked);
      };
      #endif // MAINWINDOW_H
      
      

      mainWindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          labCurFile=new QLabel("當(dāng)前文件",this);
          labCurFile->setMinimumWidth(200);
          labCellPos=new QLabel("當(dāng)前單元格",this);
          labCellPos->setMinimumWidth(200);
          labCellText=new QLabel("單元格內(nèi)容",this);
          labCellText->setMinimumWidth(200);
      
          ui->statusbar->addWidget(labCurFile);
          ui->statusbar->addWidget(labCellPos);
          ui->statusbar->addWidget(labCellText);
      
          m_model= new QStandardItemModel(2,fixedColum,this);
          m_selection= new QItemSelectionModel(m_model,this);
          ui->tableView->setModel(m_model);
          ui->tableView->setSelectionModel(m_selection);
          ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
          ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
      
          connect(m_selection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(do_currentChanged(QModelIndex,QModelIndex)));
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::iniModelData(QStringList &fileContent)
      {
          int rowCount=fileContent.size();
          m_model->setRowCount(rowCount-1);
      
          QString header=fileContent.at(0);
          QStringList headerList=header.split(QRegularExpression(R"(\s+)"),Qt::SkipEmptyParts);
          m_model->setHorizontalHeaderLabels(headerList);
          for(int i=1;i<rowCount;i++){
              QString lineText=fileContent.at(i);
              QStringList tempList=lineText.split(QRegularExpression(R"(\s+)"),Qt::SkipEmptyParts);
      
              QStandardItem *item= new QStandardItem(tempList.at(0));
              item->setCheckable(true);
              item->setBackground(QBrush(Qt::yellow));
              if(tempList.at(0)=="0")
                  item->setCheckState(Qt::Unchecked);
              else
                  item->setCheckState(Qt::Checked);
              m_model->setItem(i-1,0,item);
              for(int j=1;j<=5;j++){
                  item=new QStandardItem(tempList.at(j));
                  m_model->setItem(i-1,j,item);
              }
          }
      
      }
      
      void MainWindow::do_currentChanged(const QModelIndex &current, const QModelIndex &previous)
      {
          if(current.isValid()){
              labCellPos->setText(QString::asprintf("當(dāng)前單元格:%d行,%d列",current.row(),current.column()));
              QStandardItem *tempItem= m_model->itemFromIndex(current);
              labCellText->setText(QString("單元格內(nèi)容:%1").arg(tempItem->text()));
              ui->actFontBold->setChecked(tempItem->font().bold());
          }
      }
      
      void MainWindow::on_actOpen_triggered()
      {
          QString curPath= QCoreApplication::applicationDirPath();
          QString fileName= QFileDialog::getOpenFileName(this,"打開一個(gè)文件",curPath,"數(shù)據(jù)文件(*.txt);所有文件(*.*)");
          if(fileName.isEmpty())
              return;
          QFile fileObject(fileName);
          if(!fileObject.open(QIODevice::ReadOnly|QIODevice::Text))
              return;
      
          QStringList fileContent;
          ui->plainTextEdit->clear();
          QTextStream tempStream(&fileObject);
          while(!tempStream.atEnd()){
              QString str=tempStream.readLine();
              ui->plainTextEdit->appendPlainText(str);
              fileContent.append(str);
          }
          fileObject.close();
          labCurFile->setText("當(dāng)前文件:"+fileName);
          ui->actAddRow->setEnabled(true);
          ui->actInsertRow->setEnabled(true);
          ui->actDeleteRow->setEnabled(true);
      
          iniModelData(fileContent);
      }
      
      
      void MainWindow::on_actAddRow_triggered()
      {
          QList<QStandardItem*>itemList;
          QString str=m_model->headerData(0,Qt::Horizontal).toString()+QString::number(m_model->rowCount());
          QStandardItem *item=new QStandardItem(str);
          item->setColumnCount(6);
          item->setCheckable(true);
          item->setCheckState(Qt::Checked);
          item->setBackground(Qt::yellow);
          itemList<<item;
          for(int i=0;i<m_model->columnCount()-1;i++){
              item=new QStandardItem("0");
              itemList<<item;
          }
          m_model->appendRow(itemList);
          m_selection->clearSelection();
          m_selection->setCurrentIndex(m_model->index(m_model->rowCount()-1,0),QItemSelectionModel::Select);
      }
      
      
      
      void MainWindow::on_actInsertRow_triggered()
      {
          QModelIndex index= ui->tableView->currentIndex();
          QList<QStandardItem*>itemList;
          QString str=m_model->headerData(0,Qt::Horizontal).toString()+QString::number(m_model->rowCount());
          QStandardItem *item=new QStandardItem(str);
          item->setColumnCount(6);
          item->setCheckable(true);
          item->setCheckState(Qt::Checked);
          item->setBackground(Qt::yellow);
          itemList<<item;
          for(int i=0;i<m_model->columnCount()-1;i++){
              item=new QStandardItem("0");
              itemList<<item;
          }
          m_model->insertRow(index.row(),itemList);
          m_selection->clearSelection();
          m_selection->setCurrentIndex(m_model->index(index.row(),0),QItemSelectionModel::Select);
      }
      
      
      void MainWindow::on_actDeleteRow_triggered()
      {
          QModelIndex index= ui->tableView->currentIndex();
          m_model->removeRow(index.row());
      }
      
      
      void MainWindow::on_actModelData_triggered()
      {
          ui->plainTextEdit->clear();
          QStandardItem *item;
          QString str="";
      
          for(int i=0;i<m_model->columnCount();i++){
              item=m_model->horizontalHeaderItem(i);
              str+=item->text();
              str+='\t';
          }
          ui->plainTextEdit->appendPlainText(str);
          for(int i=0;i<m_model->rowCount();i++){
              str.clear();
              item=m_model->item(i,0);
              if(item->checkState()==Qt::Checked)
                  str+="是 ";
              else
                  str+="否 ";
              for(int j=0;j<m_model->columnCount();j++){
                  item=m_model->item(i,j);
                  str+=item->text();
                  str+='\t';
              }
              ui->plainTextEdit->appendPlainText(str);
          }
      }
      
      
      void MainWindow::on_actAlignLeft_triggered()
      {
          QStandardItem *item;
          QModelIndexList indexList;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              item->setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      
      
      void MainWindow::on_actAlignCenter_triggered()
      {
          QStandardItem *item;
          QModelIndexList indexList;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      
      
      void MainWindow::on_actAlignRight_triggered()
      {
          QStandardItem *item;
          QModelIndexList indexList;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      
      
      
      void MainWindow::on_actFontBold_triggered(bool checked)
      {
          QStandardItem *item;
          QModelIndexList indexList;
          QFont font;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              font=item->font();
              font.setBold(checked);
              item->setFont(font);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      

      自定義代理

      在模型-視圖結(jié)構(gòu)中,代理的作用就是在視圖組件進(jìn)入編輯狀態(tài)編輯某個(gè)項(xiàng)時(shí),提供一個(gè)臨時(shí)的編輯器用于數(shù)據(jù)編輯,編輯完成后再把數(shù)據(jù)提交給數(shù)據(jù)模型.

      QTableView等視圖組件的代理默認(rèn)提供QLineEdit編輯框,在這個(gè)編輯框里可以輸入任何數(shù)據(jù),所以比較通用.

      但是某些情況,我們也希望根據(jù)數(shù)據(jù)類型不同使用不同的編輯器,若要使用這樣的功能,就需要使用自定義代理.

      若要替換QTableView組件提供的默認(rèn)代理組件,就需要為QTableView組件的某列或某個(gè)單元格設(shè)置自定義代理.

      自定義代理類需要從QStyledItemDelegate類繼承,創(chuàng)建自定義代理類的實(shí)例后,再將其設(shè)置為整個(gè)視圖組件或視圖組件的某行或某列的代理.

      QAbstractItemView類定義了設(shè)置自定義代理的3個(gè)函數(shù),定義如下:

      • void setItemDelegate(QAbstractItemDelegate*delegate)
      • void setItemDelegateForColumn(int column,QAbstractItemDelegate*delegate)
      • void setItemDelegateForRow(int row,QAbstractItemDelegate*delegate)

      其中,delegate是創(chuàng)建的自定義代理類的實(shí)例對(duì)象.

      QStyledItemDelegate是視圖組件使用的默認(rèn)代理類,自定義代理類需要從QStyledItemDelegate類繼承.

      要自定義一個(gè)代理類,必須重新實(shí)現(xiàn)QStyledItemDelegate中定義的4個(gè)虛函數(shù).

      • QWidget*QStyledItemDelegate::createEditor(QWidget*parent,const QStyleOptionViewItem &option,const QModelIndex &index)//用于創(chuàng)建代理編輯器
      • void QStyledItemDelegate::setEditorData(QWidget *editor,const QModelIndex &index)
        //用于從數(shù)據(jù)模型獲取項(xiàng)的某個(gè)角色(一般為EditRole),然后將其設(shè)置為代理編輯器上顯示的數(shù)據(jù)
      • void QStyledItemDelegate::setModelData(QWidget*editor,QAbstractItemModel *model,const QModelIndex &index)//完成對(duì)當(dāng)前單元格的編輯
      • void QStyledItemDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index)//為臨時(shí)組件設(shè)置合適的大小

      下面提供一個(gè)使用自定義代理的例子,改編自上面QStandardItemModel綜合使用例子:

      tcombobox_delegate.h

      #ifndef TCOMBOBOXDELEGATE_H
      #define TCOMBOBOXDELEGATE_H
      
      #include <QObject>
      #include <QStyledItemDelegate>
      #include <QComboBox>
      
      class TComboBoxDelegate : public QStyledItemDelegate
      {
          Q_OBJECT
      public:
          explicit TComboBoxDelegate(QObject *parent = nullptr);
      
          // QAbstractItemDelegate interface
      public:
          void setItems(QStringList items,bool editable);
          virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
          virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
          virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
          virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
      private:
          QStringList m_itemList;
          bool m_editable;
      };
      
      #endif // TCOMBOBOXDELEGATE_H
      

      tfloat_spinbox_delegate.h

      #ifndef TFLOATSPINBOXDELEGATE_H
      #define TFLOATSPINBOXDELEGATE_H
      
      #include <QObject>
      #include <QStyledItemDelegate>
      #include <QDoubleSpinBox>
      
      class TFloatSpinBoxDelegate : public QStyledItemDelegate
      {
          Q_OBJECT
      public:
          explicit TFloatSpinBoxDelegate(QObject *parent = nullptr);
      
          // QAbstractItemDelegate interface
      public:
          virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
          virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
          virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
          virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
      };
      
      #endif // TFLOATSPINBOXDELEGATE_H
      

      tspinbox_delegate.h

      #ifndef TSPINBOXDELEGATE_H
      #define TSPINBOXDELEGATE_H
      
      #include <QObject>
      #include <QSpinBox>
      #include <QQmlEngine>
      #include <QStyledItemDelegate>
      
      class TSpinBoxDelegate : public QStyledItemDelegate
      {
          QML_ELEMENT
      public:
          explicit TSpinBoxDelegate(QObject *parent=nullptr);
      
          // QAbstractItemDelegate interface
      public:
          virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
          virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
          virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
          virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
      };
      #endif // TSPINBOXDELEGATE_H
      

      mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QLabel>
      #include <QStandardItemModel>
      #include <QItemSelectionModel>
      #include <QFileDialog>
      #include <QString>
      #include <QStyledItemDelegate>
      
      #include "tspinbox_delegate.h"
      #include "tfloat_spinbox_delegate.h"
      #include "tcombobox_delegate.h"
      
      QT_BEGIN_NAMESPACE
      namespace Ui {
      class MainWindow;
      }
      QT_END_NAMESPACE
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui;
          QLabel *labCurFile,*labCellPos,*labCellText;
          const int fixedColum=6;
          QStandardItemModel *m_model;
          QItemSelectionModel *m_selection;
      
          TSpinBoxDelegate* intSpinDelegate;
          TFloatSpinBoxDelegate* doubleSpinDelegate;
          TComboBoxDelegate* comboBoxDelegate;
      
          void iniModelData(QStringList &fileContent);
      private slots:
          void do_currentChanged(const QModelIndex&current,const QModelIndex&previous);
          void on_actOpen_triggered();
          void on_actAddRow_triggered();
          void on_actInsertRow_triggered();
          void on_actDeleteRow_triggered();
          void on_actModelData_triggered();
          void on_actAlignLeft_triggered();
          void on_actAlignCenter_triggered();
          void on_actAlignRight_triggered();
          void on_actFontBold_triggered(bool checked);
      };
      #endif // MAINWINDOW_H
      

      tcombobox_delegate.cpp

      #include "tcombobox_delegate.h"
      
      TComboBoxDelegate::TComboBoxDelegate(QObject *parent)
          : QStyledItemDelegate{parent}
      {
      
      }
      
      void TComboBoxDelegate::setItems(QStringList items, bool editable)
      {
          m_itemList=items;
          m_editable=editable;
      }
      
      QWidget *TComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          Q_UNUSED(option);
          Q_UNUSED(index);
      
          QComboBox *editor=new QComboBox(parent);
          editor->setEditable(m_editable);
          for(auto iter:m_itemList)
              editor->addItem(iter);
          return editor;
      }
      
      void TComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      {
          QComboBox *comboBox=dynamic_cast<QComboBox*>(editor);
          QString str=index.model()->data(index,Qt::EditRole).toString();
          comboBox->setCurrentText(str);
      }
      
      void TComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      {
          QComboBox *comboBox=dynamic_cast<QComboBox*>(editor);
          QString str=comboBox->currentText();
          model->setData(index,str,Qt::EditRole);
      }
      
      void TComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          Q_UNUSED(index);
          editor->setGeometry(option.rect);
      }
      

      tfloat_spinbox_delegate.cpp

      #include "tfloat_spinbox_delegate.h"
      
      TFloatSpinBoxDelegate::TFloatSpinBoxDelegate(QObject *parent)
          : QStyledItemDelegate{parent}
      {
      
      }
      
      QWidget *TFloatSpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          Q_UNUSED(option);
          Q_UNUSED(index);
          QDoubleSpinBox *editor=new QDoubleSpinBox(parent);
          editor->setFrame(false);
          editor->setMinimum(0);
          editor->setMaximum(50000);
          return editor;
      }
      
      void TFloatSpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      {
          QDoubleSpinBox *spinBox=dynamic_cast<QDoubleSpinBox*>(editor);
          double value=index.model()->data(index,Qt::EditRole).toDouble();
          spinBox->setValue(value);
      }
      
      void TFloatSpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      {
          QDoubleSpinBox *spinBox=dynamic_cast<QDoubleSpinBox*>(editor);
          double value=spinBox->value();
          model->setData(index,value);
      }
      
      void TFloatSpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          Q_UNUSED(index);
          editor->setGeometry(option.rect);
      }
      

      tspinbox_delegate.cpp

      #include "tspinbox_delegate.h"
      
      TSpinBoxDelegate::TSpinBoxDelegate(QObject *parent)
          :QStyledItemDelegate(parent)
      {
      
      }
      
      QWidget *TSpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          Q_UNUSED(option);
          Q_UNUSED(index);
          QSpinBox *editor=new QSpinBox(parent);
          editor->setFrame(false);
          editor->setMinimum(0);
          editor->setMaximum(50000);
          return editor;
      }
      
      void TSpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      {
          QSpinBox *spinBox=dynamic_cast<QSpinBox*>(editor);
          int value=index.model()->data(index,Qt::EditRole).toInt();
          spinBox->setValue(value);
      }
      
      void TSpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      {
          QSpinBox *spinBox=dynamic_cast<QSpinBox*>(editor);
          int value=spinBox->value();
          model->setData(index,value);
      }
      
      void TSpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          Q_UNUSED(index);
          editor->setGeometry(option.rect);
      }
      

      mainwindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          labCurFile=new QLabel("當(dāng)前文件",this);
          labCurFile->setMinimumWidth(200);
          labCellPos=new QLabel("當(dāng)前單元格",this);
          labCellPos->setMinimumWidth(200);
          labCellText=new QLabel("單元格內(nèi)容",this);
          labCellText->setMinimumWidth(200);
      
          ui->statusbar->addWidget(labCurFile);
          ui->statusbar->addWidget(labCellPos);
          ui->statusbar->addWidget(labCellText);
      
          m_model= new QStandardItemModel(2,fixedColum,this);
          m_selection= new QItemSelectionModel(m_model,this);
          ui->tableView->setModel(m_model);
          ui->tableView->setSelectionModel(m_selection);
          ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
          ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
      
          intSpinDelegate= new TSpinBoxDelegate;
          ui->tableView->setItemDelegateForColumn(1,intSpinDelegate);
      
          doubleSpinDelegate= new TFloatSpinBoxDelegate;
          ui->tableView->setItemDelegateForColumn(3,doubleSpinDelegate);
          ui->tableView->setItemDelegateForColumn(4,doubleSpinDelegate);
          ui->tableView->setItemDelegateForColumn(5,doubleSpinDelegate);
      
          comboBoxDelegate= new TComboBoxDelegate;
          QStringList strList;
          strList<<"名字1"<<"名字2"<<"名字3";
          comboBoxDelegate->setItems(strList,true);
          ui->tableView->setItemDelegateForColumn(0,comboBoxDelegate);
      
          connect(m_selection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(do_currentChanged(QModelIndex,QModelIndex)));
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::iniModelData(QStringList &fileContent)
      {
          int rowCount=fileContent.size();
          m_model->setRowCount(rowCount-1);
      
          QString header=fileContent.at(0);
          QStringList headerList=header.split(QRegularExpression(R"(\s+)"),Qt::SkipEmptyParts);
          m_model->setHorizontalHeaderLabels(headerList);
          for(int i=1;i<rowCount;i++){
              QString lineText=fileContent.at(i);
              QStringList tempList=lineText.split(QRegularExpression(R"(\s+)"),Qt::SkipEmptyParts);
      
              QStandardItem *item= new QStandardItem(tempList.at(0));
              item->setCheckable(true);
              item->setBackground(QBrush(Qt::yellow));
              if(tempList.at(0)=="0")
                  item->setCheckState(Qt::Unchecked);
              else
                  item->setCheckState(Qt::Checked);
              m_model->setItem(i-1,0,item);
              for(int j=1;j<=5;j++){
                  item=new QStandardItem(tempList.at(j));
                  m_model->setItem(i-1,j,item);
              }
          }
      
      }
      
      void MainWindow::do_currentChanged(const QModelIndex &current, const QModelIndex &previous)
      {
          if(current.isValid()){
              labCellPos->setText(QString::asprintf("當(dāng)前單元格:%d行,%d列",current.row(),current.column()));
              QStandardItem *tempItem= m_model->itemFromIndex(current);
              labCellText->setText(QString("單元格內(nèi)容:%1").arg(tempItem->text()));
              ui->actFontBold->setChecked(tempItem->font().bold());
          }
      }
      
      void MainWindow::on_actOpen_triggered()
      {
          QString curPath= QCoreApplication::applicationDirPath();
          QString fileName= QFileDialog::getOpenFileName(this,"打開一個(gè)文件",curPath,"數(shù)據(jù)文件(*.txt);所有文件(*.*)");
          if(fileName.isEmpty())
              return;
          QFile fileObject(fileName);
          if(!fileObject.open(QIODevice::ReadOnly|QIODevice::Text))
              return;
      
          QStringList fileContent;
          ui->plainTextEdit->clear();
          QTextStream tempStream(&fileObject);
          while(!tempStream.atEnd()){
              QString str=tempStream.readLine();
              ui->plainTextEdit->appendPlainText(str);
              fileContent.append(str);
          }
          fileObject.close();
          labCurFile->setText("當(dāng)前文件:"+fileName);
          ui->actAddRow->setEnabled(true);
          ui->actInsertRow->setEnabled(true);
          ui->actDeleteRow->setEnabled(true);
      
          iniModelData(fileContent);
      }
      
      
      void MainWindow::on_actAddRow_triggered()
      {
          QList<QStandardItem*>itemList;
          QString str=m_model->headerData(0,Qt::Horizontal).toString()+QString::number(m_model->rowCount());
          QStandardItem *item=new QStandardItem(str);
          item->setColumnCount(6);
          item->setCheckable(true);
          item->setCheckState(Qt::Checked);
          item->setBackground(Qt::yellow);
          itemList<<item;
          for(int i=0;i<m_model->columnCount()-1;i++){
              item=new QStandardItem("0");
              itemList<<item;
          }
          m_model->appendRow(itemList);
          m_selection->clearSelection();
          m_selection->setCurrentIndex(m_model->index(m_model->rowCount()-1,0),QItemSelectionModel::Select);
      }
      
      
      
      void MainWindow::on_actInsertRow_triggered()
      {
          QModelIndex index= ui->tableView->currentIndex();
          QList<QStandardItem*>itemList;
          QString str=m_model->headerData(0,Qt::Horizontal).toString()+QString::number(m_model->rowCount());
          QStandardItem *item=new QStandardItem(str);
          item->setColumnCount(6);
          item->setCheckable(true);
          item->setCheckState(Qt::Checked);
          item->setBackground(Qt::yellow);
          itemList<<item;
          for(int i=0;i<m_model->columnCount()-1;i++){
              item=new QStandardItem("0");
              itemList<<item;
          }
          m_model->insertRow(index.row(),itemList);
          m_selection->clearSelection();
          m_selection->setCurrentIndex(m_model->index(index.row(),0),QItemSelectionModel::Select);
      }
      
      
      void MainWindow::on_actDeleteRow_triggered()
      {
          QModelIndex index= ui->tableView->currentIndex();
          m_model->removeRow(index.row());
      }
      
      
      void MainWindow::on_actModelData_triggered()
      {
          ui->plainTextEdit->clear();
          QStandardItem *item;
          QString str="";
      
          for(int i=0;i<m_model->columnCount();i++){
              item=m_model->horizontalHeaderItem(i);
              str+=item->text();
              str+='\t';
          }
          ui->plainTextEdit->appendPlainText(str);
          for(int i=0;i<m_model->rowCount();i++){
              str.clear();
              item=m_model->item(i,0);
              if(item->checkState()==Qt::Checked)
                  str+="是 ";
              else
                  str+="否 ";
              for(int j=0;j<m_model->columnCount();j++){
                  item=m_model->item(i,j);
                  str+=item->text();
                  str+='\t';
              }
              ui->plainTextEdit->appendPlainText(str);
          }
      }
      
      
      void MainWindow::on_actAlignLeft_triggered()
      {
          QStandardItem *item;
          QModelIndexList indexList;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              item->setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      
      
      void MainWindow::on_actAlignCenter_triggered()
      {
          QStandardItem *item;
          QModelIndexList indexList;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      
      
      void MainWindow::on_actAlignRight_triggered()
      {
          QStandardItem *item;
          QModelIndexList indexList;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      
      
      
      void MainWindow::on_actFontBold_triggered(bool checked)
      {
          QStandardItem *item;
          QModelIndexList indexList;
          QFont font;
      
          if(!m_selection->hasSelection())
              return;
          indexList=m_selection->selectedIndexes();
      
          for(auto index:indexList){
              item= m_model->item(index.row(),index.column());
              font=item->font();
              font.setBold(checked);
              item->setFont(font);
              m_model->setItem(index.row(),index.column(),item);
          }
      }
      

      QFileSystemModel和QTreeView

      QFileSystemModel為文件系統(tǒng)提供一個(gè)模型,綜合使用QFileSystemModel和QTreeView可以以目錄樹的形式顯示本機(jī)的文件系統(tǒng),如同Windows的資源管理器一樣.

      QFileSystemModel類

      要通過QFileSystemModel獲得本機(jī)的文件系統(tǒng),需要用QFileSystemModel的函數(shù)setRootPath()設(shè)置一個(gè)根目錄.如果需要使用條件過濾,則還需要設(shè)置過濾器.

      QFileSystemModel類的主要成員函數(shù)如下:

      • QModelIndex setRootPath(const QString &newPath)//設(shè)置根目錄
      • QDir rootDirectory()//以QDir類返回目錄
      • QString rootPath()//以QString類返回目錄
      • QModelIndex index(const QString &path,int column=0)//返回目錄或文件的模型索引
      • void setFilter(QDir::Filters filters)//設(shè)置模型數(shù)據(jù)項(xiàng)過濾器
      • void setNameFilters(const QStringList &filters)//設(shè)置文件名過濾器
      • void setNameFilterDisables(bool enable)//設(shè)置文件名過濾器
      • void setOption(QFileSystemModel::Option option,bool on=true)//設(shè)置模型選項(xiàng)
      • QIcon fileIcon(const QModelIndex &index)//返回項(xiàng)的圖標(biāo)
      • QFileInfo fileInfo(const QModelIndex &index)//返回項(xiàng)的文件信息
      • QString fileName(const QModelIndex &index)//返回不含路徑的文件名或最后一級(jí)文件夾名稱
      • QString filePath(const QModelIndex &index)//返回項(xiàng)的路徑或包含路徑的文件名
      • QDateTime lastModified(const QModelIndex &index)//返回項(xiàng)的最后修改日期
      • bool isDir(const QModelIndex &index)//判斷項(xiàng)是不是一個(gè)文件夾
      • qint64 size(const QModelIndex &index)//返回文件的大小字節(jié)數(shù)
      • QString type(const QModelIndex &index)//返回項(xiàng)的類型描述文字
      • QModelIndex mkdir(const QModelIndex &parent,const QString &name)//創(chuàng)建文件夾
      • bool rmdir(const QModelIndex &index)//刪除文件夾
      • bool remove(const QModelIndex &index)//刪除文件

      相關(guān)的一些內(nèi)容:

      • QDir的枚舉值:
        • QDir::AllDirs:列出所有目錄
        • QDir::Files:列出文件
        • QDir::Drives:列出驅(qū)動(dòng)器
        • QDir::NoDotAndDotDot:不列出目錄下的'.'和'..'特殊項(xiàng)
        • QDir::Hidden:列出隱藏的文件
        • QDir::System:列出系統(tǒng)文件
      • QFileSystemModel::Option的枚舉值:
        • QFileSystemModel::Option::DontWatchForChanges:不監(jiān)視文件系統(tǒng)的變化
        • QFileSystemModel::Option::DontResolveSymlinks:不解析文件系統(tǒng)的符號(hào)連接項(xiàng)
        • QFileSystemModel::Option::DontUseCustomDirectoryIcons:不使用自定義的目錄圖標(biāo)

      QTreeView類

      QTreeView類是用于顯示樹狀模型的視圖組件,其與QFileSystemModel模型結(jié)合就可以顯示本機(jī)的文件系統(tǒng).

      如果QTreeView組件允許多選操作,就需要使用QItemSelectionModel選擇模型.

      關(guān)于文件系統(tǒng)有關(guān)內(nèi)容,后面會(huì)進(jìn)一步深入,因而暫時(shí)不用太過在意.

      下面是一個(gè)綜合使用的樣例:

      mainWindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QFileSystemModel>
      #include <QFileDialog>
      
      QT_BEGIN_NAMESPACE
      namespace Ui {
      class MainWindow;
      }
      QT_END_NAMESPACE
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      
      private slots:
          void on_actSetRootDir_triggered();
      
          void on_radOnlyDirAndFile_clicked();
      
          void on_radOnlyDir_clicked();
      
          void on_chkFliterFile_clicked(bool checked);
      
          void on_btnApplicate_clicked();
      
          void on_treeView_clicked(const QModelIndex &index);
      
      private:
          Ui::MainWindow *ui;
          QFileSystemModel *m_model;
      };
      #endif // MAINWINDOW_H
      

      mainWindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          ui->radOnlyDirAndFile->setChecked(true);
          m_model=new QFileSystemModel(this);
          ui->treeView->setModel(m_model);
          ui->listView->setModel(m_model);
          ui->tableView->setModel(m_model);
          m_model->setRootPath(QDir::currentPath());
          //ui->treeView->setRootIndex(m_model->index(QDir::currentPath()));
          connect(ui->treeView,SIGNAL(clicked(QModelIndex)),ui->listView,SLOT(setRootIndex(QModelIndex)));
          connect(ui->treeView,SIGNAL(clicked(QModelIndex)),ui->tableView,SLOT(setRootIndex(QModelIndex)));
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::on_actSetRootDir_triggered()
      {
          QString dir=QFileDialog::getExistingDirectory(this,"選擇目錄",QDir::currentPath());
      
          if(dir.isEmpty())
              return;
          ui->treeView->setRootIndex(m_model->index(dir));
          ui->listView->setRootIndex(m_model->index(dir));
          ui->tableView->setRootIndex(m_model->index(dir));
      }
      
      
      void MainWindow::on_radOnlyDirAndFile_clicked()
      {
          ui->gbFilter->setEnabled(true);
          m_model->setFilter(QDir::AllDirs|QDir::Files|QDir::NoDotAndDotDot);
      }
      
      
      void MainWindow::on_radOnlyDir_clicked()
      {
          ui->gbFilter->setEnabled(false);
          m_model->setFilter(QDir::AllDirs|QDir::NoDotAndDotDot);
      }
      
      
      void MainWindow::on_chkFliterFile_clicked(bool checked)
      {
          ui->comFileType->setEnabled(checked);
          ui->btnApplicate->setEnabled(checked);
          m_model->setNameFilterDisables(!checked);
      }
      
      
      void MainWindow::on_btnApplicate_clicked()
      {
          QStringList filter= ui->comFileType->currentText().trimmed().split(';',Qt::SkipEmptyParts);
          m_model->setNameFilters(filter);
      }
      
      
      void MainWindow::on_treeView_clicked(const QModelIndex &index)
      {
          ui->lbFileName->setText(m_model->fileName(index));
          ui->lbDirName->setText(m_model->filePath(index));
          ui->lbFileType->setText(m_model->type(index));
      
          ui->chkIsDir->setChecked(m_model->isDir(index));
      
          int sz=m_model->size(index)/1024;
          if(sz<1024)
              ui->lbFileSize->setText(QString("%1 KB").arg(sz));
          else
              ui->lbFileSize->setText(QString::asprintf("%.1f MB",sz/1024.0));
      }
      


      posted @ 2024-03-24 23:13  Mesonoxian  閱讀(406)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 在线精品自拍亚洲第一区| 澳门永久av免费网站| 国产SM重味一区二区三区| 久久午夜无码鲁丝片直播午夜精品| 婷婷五月综合激情| 国产对白老熟女正在播放| 巨熟乳波霸若妻在线播放| 久久av中文字幕资源网| 亚洲色大成成人网站久久| 国产精品成人中文字幕| 国产一区二区亚洲av| 免费网站看sm调教视频| 国产高清视频一区二区三区| 无码人妻aⅴ一区二区三区蜜桃| 中文字幕无码色综合网| 欧美人与动欧交视频| 国产无人区码一区二区| 99久久国语露脸精品国产| 国产精品国产精品一区精品| 插插无码视频大全不卡网站| 日韩av中文字幕有码| 亚洲全乱码精品一区二区| 成A人片亚洲日本久久| 里番全彩爆乳女教师| 无码免费大香伊蕉在人线国产| 美女18禁一区二区三区视频| 亚洲色最新高清AV网站| 97在线观看视频免费| 亚洲情A成黄在线观看动漫尤物 | 亚洲天堂在线免费| a级国产乱理伦片在线观看al| 亚洲成女人图区一区二区| 成人永久性免费在线视频| 四虎国产精品永久在线下载| 全部免费毛片在线播放| 亚洲精品自拍视频在线看| 老色鬼在线精品视频| 亚洲高清WWW色好看美女| 国产精品自在自线视频| AV最新高清无码专区| 精品人妻码一区二区三区|