1. 程式人生 > >Qt第十二天

Qt第十二天

QStandardItemModel的使用

實現功能:
開啟一個文字檔案,該檔案為二維資料檔案,通過字串處理獲取表頭和各行各列資料,匯入到QStandardItemModel資料模型
編輯修改資料模型的資料
設定資料模型中某項的不同角色的資料
通過QItemSelectionModel獲取檢視元件上當前單元格
將資料模型中的資料顯示到QPlainTextEdit元件中
將修改後的資料模型另存為一個文字檔案

mainwindow.h檔案

#ifndef MAINWINDOW_H
#define MAINWINDOW_H


#include <QMainWindow>
#include <QLabel>
#include <QStandardItemModel>
#include <QItemSelectionModel>


namespace Ui {
class MainWindow;
}




#define FixedColumCount   6  //固定列數為6
class MainWindow : public QMainWindow
{
    Q_OBJECT


public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private:
    Ui::MainWindow *ui;




    QLabel *LabCurFile;//表示當前檔案
    QLabel *LabCellPos;//當前單元格行列號
    QLabel *LabCellText;//當前單元格內容
    QStandardItemModel  *theModel;//加入標頭檔案<QStandardItemModel>
                                  //資料模型
    QItemSelectionModel *theSelection;//加入標頭檔案<QItemSelectionModel>
                                      //選擇資料模型
    void iniModelFromStringList(QStringList&);//從StringList初始化資料模型


private slots:
    //自定義槽函式
    void on_currentChanged(const QModelIndex &current,const QModelIndex &previous);
    void on_actOpen_triggered();
    void on_actAppend_triggered();
    void on_actInsert_triggered();
    void on_actDelete_triggered();
    void on_actAlignLeft_triggered();
    void on_actAlignCenter_triggered();
    void on_actAlignRight_triggered();
    void on_actFontBold_triggered();
    void on_actFontBold_triggered(bool checked);
    void on_actModelData_triggered();
    void on_actSave_triggered();
};


#endif // MAINWINDOW_H

mainwindow.cpp檔案

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTableView>
#include <QFileDialog>
#include <QTextStream>




MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //進行介面初始化,資料模型和選擇模型的建立,訊號與槽的關聯
    setCentralWidget(ui->splitter);
    theModel=new QStandardItemModel(2,FixedColumCount,this);//2*6的資料模型
    theSelection=new QItemSelectionModel(theModel);//選擇模型
    connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
    //Selection的currentChanged訊號()與on_currentChanged()關聯
    ui->tableView->setModel(theModel);
    ui->tableView->setSelectionModel(theSelection);
    ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);//允許選中多行
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);//設定選擇模式為單元格
    //狀態列標籤
    LabCurFile = new QLabel("當前檔案:",this);
    LabCurFile->setMinimumWidth(200);
    LabCellPos = new QLabel("當前單元格:",this);
    LabCellPos->setMinimumWidth(180);
    LabCellPos->setAlignment(Qt::AlignHCenter);//設為中心
    LabCellText = new QLabel("單元格內容:",this);
    LabCellText->setMinimumWidth(150);


    ui->statusBar->addWidget(LabCurFile);
    ui->statusBar->addWidget(LabCellPos);
    ui->statusBar->addWidget(LabCellText);
}


MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(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;
        ui->actFontBold->setChecked(font.bold());//更新actFontBold的check狀態
    }
}




void MainWindow::on_actOpen_triggered()//開啟檔案
{
    QString curPath=QCoreApplication::applicationDirPath();
    QString aFileName=QFileDialog::getOpenFileName(this,"開啟一個檔案",curPath,"資料檔案(*.txt);;所有檔案(*.*)");
    if(aFileName.isEmpty())//如果未選擇檔案,退出
    {
        return;
    }
    QStringList fFileContent;//檔案內容字串列表
    QFile aFile(aFileName); //以檔案方式讀出
    if(aFile.open(QIODevice::ReadOnly|QIODevice::Text))//以只讀文字方式開啟檔案
    {
        QTextStream aStream(&aFile);//以文字流讀取檔案
                                    //加入標頭檔案<QTextStream>
        ui->plainTextEdit->clear();//清空
        while (!aStream.atEnd())
        {
            QString str=aStream.readLine();//讀取檔案的一行
            ui->plainTextEdit->appendPlainText(str); //新增到文字框顯示
            fFileContent.append(str); //新增到 StringList
        }
        aFile.close();//關閉檔案
        this->LabCurFile->setText("當前檔案:"+aFileName);//狀態列顯示
        //更新Actions的enable屬性
        ui->actAppend->setEnabled(true);
        ui->actInsert->setEnabled(true);
        ui->actDelete->setEnabled(true);
        ui->actSave->setEnabled(true);


        iniModelFromStringList(fFileContent);//初始化資料模型
    }
}
void MainWindow::iniModelFromStringList(QStringList& aFileContent)//從一個StringList 獲取資料,初始化資料Model
{
    int rowCnt=aFileContent.count(); //獲取文字行數,其中第1行是標題
    theModel->setRowCount(rowCnt-1); //實際資料行數


    //設定表頭
    QString header=aFileContent.at(0);//第1行是表頭
    //一個或多個空格、TAB等分隔符隔開的字串, 分解為一個StringList
    QStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts);
    theModel->setHorizontalHeaderLabels(headerList); //設定表頭文字


    //設定表格資料
    int j;
    QStandardItem   *aItem;
    for (int i=1;i<rowCnt;i++)
    {
        QString aLineText=aFileContent.at(i); //獲取 資料區 的一行
        //一個或多個空格、TAB等分隔符隔開的字串, 分解為一個StringList
        QStringList tmpList=aLineText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
        for (j=0;j<FixedColumCount-1;j++) //tmpList的行數等於FixedColumnCount, 固定的
        { //不包含最後一列
            aItem=new QStandardItem(tmpList.at(j));//建立item
            theModel->setItem(i-1,j,aItem); //為模型的某個行列位置設定Item
        }


        aItem=new QStandardItem(headerList.at(j));//最後一列是Checkable,需要設定
        aItem->setCheckable(true); //設定為Checkable
        if (tmpList.at(j)=="0")
            aItem->setCheckState(Qt::Unchecked); //根據資料設定check狀態
        else
            aItem->setCheckState(Qt::Checked);
        theModel->setItem(i-1,j,aItem); //為模型的某個行列位置設定Item
    }
}


void MainWindow::on_actAppend_triggered()//在最後新增行
{
    QList<QStandardItem*> aItemList;//列表類
    QStandardItem *aItem;
    for(int i=0;i<FixedColumCount-1;i++)//不包含最後一列
    {
        aItem=new QStandardItem("未知");//建立Item為0
        aItemList<<aItem;//新增到列表
    }
    //獲取最後一列的表頭文字
    QString str=theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();//獲取表頭
    aItem=new QStandardItem(str);
    aItem->setCheckable(true);
    aItemList<<aItem;//新增到列表


    theModel->insertRow(theModel->rowCount(),aItemList);//新增一行


    QModelIndex curIndex=theModel->index(theModel->rowCount()-1,0);//改變索引值,設為新增行的第一列
    theSelection->clearSelection();
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//改變選中的單元格為新增行的第一個單元格
}


void MainWindow::on_actInsert_triggered()//插入行
{
    QList<QStandardItem*> aItemList;//列表類
    QStandardItem *aItem;
    for(int i=0;i<FixedColumCount-1;i++)//不包含最後一列
    {
        aItem=new QStandardItem("未知1");//建立Item為0
        aItemList<<aItem;//新增到列表
    }
    //獲取最後一列的表頭文字
    QString str=theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();//獲取表頭
    aItem=new QStandardItem(str);
    aItem->setCheckable(true);
    aItemList<<aItem;//新增到列表


    QModelIndex curIndex=theSelection->currentIndex();//獲取當前的索引
    theModel->insertRow(curIndex.row(),aItemList);//在當前行插入新行
    curIndex=theModel->index(curIndex.row(),0);
    theSelection->clearSelection();
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//改變選中的單元格為插入行的第一個單元格
}


void MainWindow::on_actDelete_triggered()//刪除行
{
    QModelIndex curIndex=theSelection->currentIndex();
    if(curIndex.row()==theModel->rowCount()-1)//如果是最後一行
    {
        theModel->removeRow(curIndex.row());//移除這一行
    }
    else
    {
        theModel->removeRow(curIndex.row());//移除
        theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//重新設定選中行
    }
}


void MainWindow::on_actAlignLeft_triggered()//左對齊
{
    if(!theSelection->hasSelection())
        return;
    //獲取選中的單元格的模型索引列表
    QModelIndexList selectedIndex=theSelection->selectedIndexes();
    for(int i=0;i<selectedIndex.count();i++)
    {
        QModelIndex index=selectedIndex.at(i);//獲取一個模型索引
        QStandardItem *aItem=theModel->itemFromIndex(index);//通過索引值獲取物件
        aItem->setTextAlignment(Qt::AlignLeft);//設定為左對齊
    }
}


void MainWindow::on_actAlignCenter_triggered()//居中對齊
{
    if(!theSelection->hasSelection())
        return;


    QModelIndexList selectedIndex=theSelection->selectedIndexes();
    for(int i=0;i<selectedIndex.count();i++)
    {
        QModelIndex index=selectedIndex.at(i);//獲取一個模型索引
        QStandardItem *aItem=theModel->itemFromIndex(index);//通過索引值獲取物件
        aItem->setTextAlignment(Qt::AlignHCenter);//設定為左對齊
    }
}


void MainWindow::on_actAlignRight_triggered()//右對齊
{
    if(!theSelection->hasSelection())
        return;


    QModelIndexList selectedIndex=theSelection->selectedIndexes();
    for(int i=0;i<selectedIndex.count();i++)
    {
        QModelIndex index=selectedIndex.at(i);//獲取一個模型索引
        QStandardItem *aItem=theModel->itemFromIndex(index);//通過索引值獲取物件
        aItem->setTextAlignment(Qt::AlignRight);//設定為右對齊
    }
}


void MainWindow::on_actFontBold_triggered()
{


}


void MainWindow::on_actFontBold_triggered(bool checked)//設定為粗體
{
    if(!theSelection->hasSelection())
    {
        return;
    }
    QModelIndexList selectedIndex=theSelection->selectedIndexes();
    for(int i=0;i<selectedIndex.count();i++)
    {
        QModelIndex index=selectedIndex.at(i);//獲取一個模型索引
        QStandardItem *aItem=theModel->itemFromIndex(index);//通過索引值獲取物件
        QFont font=aItem->font();
        font.setBold(checked);//設定為粗體
        aItem->setFont(font);
    }
}


void MainWindow::on_actModelData_triggered()//資料模型預覽
{
    ui->plainTextEdit->clear(); //清空
    QStandardItem   *aItem;
    QString str;


   //獲取表頭文字
    int i,j;
    for (i=0;i<theModel->columnCount();i++)
    { //
        aItem=theModel->horizontalHeaderItem(i); //獲取表頭的一個項資料
        str=str+aItem->text()+"\t"; //用TAB間隔文字
    }
    ui->plainTextEdit->appendPlainText(str); //新增為文字框的一行


    //獲取資料區的每行
    for (i=0;i<theModel->rowCount();i++)
    {
        str="";
        for(j=0;j<theModel->columnCount()-1;j++)
        {
            aItem=theModel->item(i,j);
            str=str+aItem->text()+QString::asprintf("\t"); //以 TAB分隔
        }


        aItem=theModel->item(i,j); //最後一行是邏輯型
        if (aItem->checkState()==Qt::Checked)
            str=str+"1";
        else
            str=str+"0";


         ui->plainTextEdit->appendPlainText(str);
    }


}


void MainWindow::on_actSave_triggered()//另存檔案
{
    QString curPath=QCoreApplication::applicationDirPath(); //獲取應用程式的路徑
    //呼叫開啟檔案對話方塊選擇一個檔案
    QString aFileName=QFileDialog::getSaveFileName(this,tr("選擇一個檔案"),curPath,"資料檔案(*.txt);;所有檔案(*.*)");
    if (aFileName.isEmpty()) //未選擇檔案,退出
        return;
    QFile aFile(aFileName);
    if (!(aFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)))
        return; //以讀寫、覆蓋原有內容方式開啟檔案


    QTextStream aStream(&aFile); //用文字流讀取檔案
    QStandardItem   *aItem;
    int i,j;
    QString str;
    ui->plainTextEdit->clear();


    //獲取表頭文字
    for (i=0;i<theModel->columnCount();i++)
    {
        aItem=theModel->horizontalHeaderItem(i); //獲取表頭的項資料
        str=str+aItem->text()+"\t\t";  //以TAB見隔開
    }
    aStream<<str<<"\n";  //檔案裡需要加入換行符 \n
    ui->plainTextEdit->appendPlainText(str);


    //獲取資料區文字
    for ( i=0;i<theModel->rowCount();i++)
    {
        str="";
        for( j=0;j<theModel->columnCount()-1;j++)
        {
            aItem=theModel->item(i,j);
            str=str+aItem->text()+QString::asprintf("\t\t");
        }


        aItem=theModel->item(i,j); //最後一列是邏輯型
        if (aItem->checkState()==Qt::Checked)
            str=str+"1";
        else
            str=str+"0";


         ui->plainTextEdit->appendPlainText(str);
         aStream<<str<<"\n";
    }
}

mainwindow.ui檔案

在這裡插入圖片描述

執行結果

在這裡插入圖片描述