QStanardItemModel、QTableView和QitemSelectionModel

一、三者关系

1.QStanardItemModel

       1) QStandardItemModel是基于项的模型类,每个项是QStanardItem对象,它与QTableView组成模型视图/结构,可以实现二维数组的管理。

2.QStandardItem

       1) QStandardItem存储乐一个项的各种特性参数,也可以存储用户自定义数据。

        2)一个项可以添加子项,子项也可以是QStanardItem类型的对象,QStandardItem也可以作为树状模型的项。

3.QTableView

        1)二维表格试图组件类,基本显示单元是单元格。

        2)setModle() 可设置一个QStanardItemModel类的数据模型,之后一个单元格显示数据模型中的一个项目。

4.QItemSelectionModel

        1)选择模型,可通过setModel()为选择模型设置数据类型。

        2)用于跟踪视图组件上的选择操作,给出选择范围。

二、实现

1.窗口类定义和初始化

        1)头文件class声明,在.c文件引入头文件。

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:

    QToolBar *toolBarAbove;
    QLabel *lab;//当前文件
    QLabel *labFile;//显示文件路径
    QLabel *lab2;//当前单元格坐标
    QLabel *labCoord;//显示单元格坐标
    QLabel *lab3;//单元格内容
    QLabel *labInformation;//显示单元格内容
    QStandardItemModel *m_stdItemModel;//数据模型
    QItemSelectionModel *m_itemSelModel;//选择模型
    const int FixedColumnCount=6;//列

    void toolbarIni();//工具栏初始化
    void statusbarIni();//状态栏初始化
    void newRowini(QModelIndex *modelindex);//新行初始化
    void iniModelData(QStringList &aFileContent);//从stringList初始化数据模型内容
private slots:
    void do_currentChanged(const QModelIndex &current,const QModelIndex &previous);//只做址传递,存储地址,使用‘&’  作用:当选项发生变化时
    void do_act_addRow_triggered();//添加行
    void do_act_insertRow_triggered();//插入行
    void on_act_deleteRow_triggered();//删除行
    void do_act_open_triggered();//打开文件
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

2.c文件主函数初始化 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
     ui->setupUi(this);

    //QStandardItemModel    基于项数据的标准数据模型,维护一个二维的项数据数组,每个项是一个 QStandardltem 类的变量,用于存储项的数据、字体格式、对齐方式等
     m_stdItemModel =new QStandardItemModel(2,FixedColumnCount,this);
     //QItemSelectionModel  二维数据表视图组件,有多个行和多个列,每个基本显示单元是一个单元格
     //通过 setModel() 函数设置一个 QStandardItemModel 类的数据模型之后,一个单元格显示 QStandardItemModel 数据模型中的一个项
     m_itemSelModel=new QItemSelectionModel(m_stdItemModel);
     ui->tableView->setModel(m_stdItemModel);//要设置的数据模型,m_stdItemModel(QStandardItemModel模型)
     ui->tableView->setSelectionModel(m_itemSelModel);//设置选择模型
     ui->tableView->setAlternatingRowColors(true);//允许扩展选择多个单元格


    // 函数:void setSelectionMode(QAbstractItemView::SelectionMode mode);设置选择模式类型
    //SelectionMode:一个用于跟踪视图组件的单元格选择状态的类
    // NoSelection (0): 不能选择任何项。
    // SingleSelection (1): 只能选择一项,选中项与当前项为同一项,可以通过Ctrl+Click取消选择。
    // MultiSelection (2): 选中一项时,该项的选择状态将被改变,不影响其他项。可通过拖动鼠标选择多项。
    // ExtendedSelection (3): 正常选择时,一次选择一项。Ctrl+Click可以改变选中项的选择状态而不影响其他项的选择状态,Shift+Click可以根据选中项的状态决定选中项和当前项间所有项的状态。可以通过拖动鼠标选择多项。
    // ContiguousSelection (4): 正常选择时,一次选中一项。当结合Shift+Click选中某项时,选中项和当前项(即上一次的选中项)间的所有项将同时被选中或取消,这取决于选中项的状态。
    ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);//设置tableView
    //SelectItems 选择单个项目
    //SelectRows 仅选择行
    //SelectColumns 仅选择列
     ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);//选择单个项目

     toolbarIni();//工具栏初始化
     statusbarIni();//状态栏初始化
    //信号和槽
     connect(m_itemSelModel,SIGNAL(currentChanged(const QModelIndex,const QModelIndex)),this,SLOT(do_currentChanged(const QModelIndex, const QModelIndex)));
     connect(ui->act_addRow,SIGNAL(triggered()),this,SLOT(do_act_addRow_triggered()));
     connect(ui->act_insertRow,SIGNAL(triggered()),this,SLOT(do_act_insertRow_triggered()));
     connect(ui->act_open,SIGNAL(triggered()),this,SLOT(do_act_open_triggered()));
     connect(m_stdItemModel,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(modeldataChanged(QStandardItem*)));//数据模型内的数据变化

     intspinBoxDelegate=new TSpinBoxDelegate(this);
     //设置委托
     ui->tableView->setItemDelegateForColumn(0,intspinBoxDelegate);//为测深设置委托

     floatSpinDelegate=new TFloatSpinDelegate(this);
     //设置委托
     ui->tableView->setItemDelegateForColumn(1,floatSpinDelegate);//垂深
     ui->tableView->setItemDelegateForColumn(2,floatSpinDelegate);//方位
     ui->tableView->setItemDelegateForColumn(3,floatSpinDelegate);//总位移

     comboBoxDelegate=new TComboBoxDelegate(this);
     QStringList strList;
     strList<<"优"<<"良"<<"可"<<"不合格";
     comboBoxDelegate->setItems(strList,false);
     ui->tableView->setItemDelegateForColumn(4,comboBoxDelegate);

}

3.工具栏初始化

void MainWindow::toolbarIni()//工具栏初始化
{
    toolBarAbove=this->addToolBar("工具栏");//添加工具栏
    toolBarAbove->setAllowedAreas(Qt::TopToolBarArea);//设置工具栏在菜单栏下面
    toolBarAbove->setIconSize(QSize(30,30));

    QIcon  icon1(":/actIcon/icon/iocn1.png");//定义icon
    ui->act_open->setIcon(icon1);
    toolBarAbove->addAction(ui->act_open);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon2(":/actIcon/icon/iocn2.png");
    ui->act_preview->setIcon(icon2);
    ui->act_preview->setCheckable(true);
    toolBarAbove->addAction(ui->act_preview);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon3(":/actIcon/icon/iocn3.png");
    ui->act_addRow->setIcon(icon3);
    toolBarAbove->addAction(ui->act_addRow);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon4(":/actIcon/icon/iocn4.png");
    ui->act_insertRow->setIcon(icon4);
    toolBarAbove->addAction(ui->act_insertRow);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon5(":/actIcon/icon/iocn5.png");
    ui->act_deleteRow->setIcon(icon5);
    toolBarAbove->addAction(ui->act_deleteRow);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon6(":/actIcon/icon/iocn6.png");
    ui->act_left->setIcon(icon6);
    toolBarAbove->addAction(ui->act_left);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon7(":/actIcon/icon/iocn7.png");
    ui->act_middle->setIcon(icon7);
    toolBarAbove->addAction(ui->act_middle);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon8(":/actIcon/icon/iocn8.png");
    ui->act_right->setIcon(icon8);
    toolBarAbove->addAction(ui->act_right);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon9(":/actIcon/icon/iocn9.png");
    ui->act_bold->setIcon(icon9);
    toolBarAbove->addAction(ui->act_bold);
    ui->act_bold->setCheckable(true);
    toolBarAbove->addSeparator();//添加分隔条

    QIcon  icon10(":/actIcon/icon/iocn10.png");
    ui->act_exit->setIcon(icon10);
    toolBarAbove->addAction(ui->act_exit);
    toolBarAbove->addSeparator();//添加分隔条
}

4.状态栏初始化

void MainWindow::statusbarIni()
{
    lab=new QLabel("当前文件:");
    lab2=new QLabel("当前单元格:");
    lab3=new QLabel("单元格内容:");

    labFile=new QLabel(this);
    labFile->setMinimumWidth(320);
    labCoord=new QLabel(this);
    labCoord->setMinimumWidth(50);
    labInformation=new QLabel(this);
    labInformation->setMinimumWidth(50);
//逐个添加
    ui->statusbar->addWidget(lab);
    ui->statusbar->addWidget(labFile);
    ui->statusbar->addWidget(lab2);
    ui->statusbar->addWidget(labCoord);
    ui->statusbar->addWidget(lab3);
    ui->statusbar->addWidget(labInformation);
}

5.打开文件

//打开文件
void MainWindow::do_act_open_triggered()
{
    QString curPath=QCoreApplication::applicationFilePath();//用于获取应用程序的路径

    QString aFileName=QFileDialog::getOpenFileName(this,"打开一个文件",curPath,"数据文件(*.txt);;所有文件(*.*)");//接受文件路径
    ui->lineEdit->setText(aFileName);

    if(aFileName.isEmpty())
        return;//空文件退出
    QStringList aFileContent;
    QFile aFile(aFileName);
    if(aFile.open(QIODevice::ReadOnly | QIODevice::Text))//以只读文本方式打开文件
    {
        QTextStream aStream(&aFile);
        ui->plainTextEdit->clear();//清空文本,避免之前数据影响
        while(!aStream.atEnd())//不到末尾不退出
        {
            QString str=aStream.readLine();//读取一行
            ui->plainTextEdit->appendPlainText(str);//显示一行
            aFileContent.append(str);//向stringList容器添加数据
        }
        aFile.close();
 /*     .h文件的定义信息
        QLabel *lab;//当前文件
        QLabel *labFile;//显示文件路径
        QLabel *lab2;//当前单元格坐标
        QLabel *labCoord;//显示单元格坐标
        QLabel *lab3;//单元格内容
        QLabel *labInformation;//显示单元格内容
 */
        labFile->setText(aFileName);//状态栏更新
        iniModelData(aFileContent);//自定义函数,从QStringList读取
    }
}

关于getOpenFileName()函数的参数

6.iniModelData() 从stringList读取数据

        1)出现文件可以打开,但是读取的数据乱码的情况,可以将txt文档另存为的同时换另一个编码格式

void MainWindow::iniModelData(QStringList &aFileContent)//从QStringList读取文件
{
    m_stdItemModel->clear();//清空数据模型
    
    qDebug()<<"iniModeData emit!!";
    int rowCnt=aFileContent.size();//统计文本行数

    m_stdItemModel->setRowCount(rowCnt-1);//实际的行数
    QString header=aFileContent.at(0);//第一行,指向表头文字

    QStringList headerList=header.split(QRegularExpression(",|,|\\s+"),Qt::SkipEmptyParts);//以中英文逗号和空格隔开,不保留空行数据。+表示一个或多个
    qDebug()<<"headerList="<<headerList.size();

    m_stdItemModel->setHorizontalHeaderLabels(headerList);//设置表头文字

    //设置表格数据
    int j;
    QStandardItem *aItem;
    for(int i=1;i<rowCnt;i++)
    {
        QString aLineText=aFileContent.at(i);
        QStringList tmpList=aLineText.split(QRegularExpression(",|,|\\s+"),Qt::SkipEmptyParts);
        qDebug()<<tmpList.size();//分割出来的个数
        if(tmpList.size() != aFileContent.size())//如果不等于原始数据的大小,表示缺少列
        {
            for(j=0;j<tmpList.size()-1;j++)
            {
                tmpList[j]="dataError";//标明错误数据
            }
        }

        for(j=0;j<tmpList.size()-1;j++)
        {
            aItem=new QStandardItem(tmpList.at(j));
            m_stdItemModel->setItem(i-1,j,aItem);//i行,j列,逐个添加项
        }
        
        if(j==m_stdItemModel->columnCount()-1)//如果确实在最后一行
        {
            aItem=new QStandardItem(headerList.at(j));//此列
            aItem->setCheckable(true);
            aItem->setBackground(QBrush(Qt::yellow));//设置背景

            if(tmpList.at(j)=="0")
                aItem->setCheckState(Qt::Unchecked);//不勾选
            else
                aItem->setCheckState(Qt::Checked);//勾选
        }
        m_stdItemModel->setItem(i-1,j,aItem);//添加i行最后一列

    }
    if(!ui->act_preview->isChecked())//如果数据浏览Action没有勾选
        ui->plainTextEdit->clear();//立刻清除,不显示

}

7.数据浏览

//数据浏览
void MainWindow::on_act_preview_triggered(bool checked)
{
    if(checked)
    {
        //显示
        QStandardItem *aItem=m_stdItemModel->item(0,0);
        modeldataChanged(aItem);//自定义函数,当有数据变化
    }
    else
        ui->plainTextEdit->clear();
}

8.数据变化

//数据模型发生变化时,更新数据
void MainWindow::modeldataChanged(QStandardItem* aItem)
{
    if(!ui->act_preview->isChecked())//判断是否再plainTextEidt上显示数据
        return;//没选中,不显示数据

    ui->plainTextEdit->clear();

    int m_row=m_stdItemModel->rowCount();//行
    int m_column=m_stdItemModel->columnCount();//列
    qDebug()<<"行:"<<m_row<<"列:"<<m_column;

    QStringList str;//记录模型数据
    for(int i=0;i<m_column;i++)
    {
        if(m_stdItemModel->horizontalHeaderItem(i)==nullptr)
            return;//如果为空,直接退出
        str.append(m_stdItemModel->horizontalHeaderItem(i)->text());//加入表头
    }
    qDebug()<<"加入表头ok";
    for(int i=0;i<m_row;i++)
    {
        for(int j=0;j<m_column;j++)
        {
            QModelIndex aIndex=m_stdItemModel->index(i,j);//获取模型索引
            aItem=m_stdItemModel->itemFromIndex(aIndex);//根据索引获取单元格项目

            if(j==m_column-1)
            {
                qDebug()<<"计数末尾:"<<aItem->text();
                if(aItem->checkState()==Qt::Checked)
                    str.append("1");
                else
                    str.append("2");
                break;
            }
            str.append(aItem->text());
        }
    }
    qDebug()<<"读取数据ok";
    int k=1;
    QString aStr;
    for(QStringList::iterator i=str.begin();i!=str.end();i++,k++)
    {
        aStr.append(*i);
        if(k%m_column==0)
        {
            ui->plainTextEdit->appendPlainText(aStr);//打印
            aStr.clear();//清空
        }
        else
        {
            aStr.append('\t');//不是列尾,添加水平制表位
        }
    }
    qDebug()<<"打印数据ok";
}

9.信号和槽

//信号和槽
     connect(m_itemSelModel,SIGNAL(currentChanged(const QModelIndex,const QModelIndex)),this,SLOT(do_currentChanged(const QModelIndex, const QModelIndex)));
     connect(ui->act_addRow,SIGNAL(triggered()),this,SLOT(do_act_addRow_triggered()));
     connect(ui->act_insertRow,SIGNAL(triggered()),this,SLOT(do_act_insertRow_triggered()));
     connect(ui->act_open,SIGNAL(triggered()),this,SLOT(do_act_open_triggered()));
     connect(m_stdItemModel,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(modeldataChanged(QStandardItem*)));//数据模型内的数据变化

10.添加插入新行

//添加新行
void MainWindow::newRowini(QModelIndex *modelindex)
{
    //获取表格信息,初始化添加行数据
    int a_columCount=m_stdItemModel->columnCount();//获取表格列
    //存储数据
    QList<QString> *list=new QList<QString>;
    for(int i=0;i<a_columCount;i++)
    {
        list->push_back("InsertRow");//尾部添加数据
        QStandardItem* aitem=new QStandardItem;//创建item用来存储单独item(单元格)数据
        aitem->setText(list->at(i));//设置item(单元格)信息
        m_stdItemModel->setItem(modelindex->row(),i,aitem);//设置newRow行,i列,表格单元的数据
    }

    QStandardItem* insertInformation=new QStandardItem;
    //添加新行,NowRow行添加insertInformation的单元格模型
    //内部item更新后,QStandardItemModel添加一个新行
    m_stdItemModel->insertRow(modelindex->row(),insertInformation);

    //*********************************************************************************************
    //********************************************************************************************
    QModelIndex index=*modelindex;//取 传入的 modelindex 的 const QModelIndex &index             **
    ui->tableView->setCurrentIndex(index);//随添加行,但使选中的行index不变                        **
    //******************************************************************************************
    //*****************************************************************************************
}
//添加行
void MainWindow::do_act_addRow_triggered()
{

    int colcount=m_stdItemModel->columnCount();//获取列数
    qDebug()<<QString("%1").arg(colcount);
    const QList<QStandardItem*> addInformation;
    m_stdItemModel->appendRow(addInformation);
}
//插入行
void MainWindow::do_act_insertRow_triggered()
{
    //提示函数触发
    qDebug()<<"do_act_insertRow_triggered is emit!";
    //是否有单元格选中
    if(m_itemSelModel->hasSelection()==false)
    {
        return;
    }

    //获取表格选中位置
    QModelIndex modelindex=ui->tableView->currentIndex();//获取选中行
    int NowRow=modelindex.row();

    qDebug()<<NowRow;
    newRowini(&modelindex);
}

11.字体设置与段落设置

        1)判断选择选择模型提供的选择范围是否为空,再取出项,对字体设置。

        2)将获取的索引存储到一个容器当中

QModelIndexList aIndexList=m_itemSelModel->selectedIndexes();//获取索引

        3)段落同上(靠左、靠右、居中)。

//靠左
void MainWindow::on_act_left_triggered()
{
    if(!m_itemSelModel->hasSelection())//没有选择项
        return;//退出
    QModelIndexList IndexList=m_itemSelModel->selectedIndexes();//获取选择的单元格的模型索引列表(可多选)
    for(int i=0;i<IndexList.count();i++)
    {
        QModelIndex aIndex=IndexList.at(i);//获取一个模型索引
        QStandardItem* aItem=m_stdItemModel->itemFromIndex(aIndex);//根据模型索引获取单元格的项
        aItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);//设置靠左,垂直居中
    }
}

11.运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值