Qt第十三天

自定义代理

**基类为QItemDelegate,
必须实现4个函数
//自定义代理组件必须继承一下四个函数,函数的原型都是固定的
//创建编辑组件
QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
//从数据模型获取数值
void setEditorData(QWidget *editor,const QModelIndex &index) const Q_DECL_OVERRIDE;
//将代理编辑器上的值更新给数据模型
void setModelData(QWidget *editor,QAbstractItemModel model,const QModelIndex &index) const Q_DECL_OVERRIDE;
//为代理组件设置合适的大小
void updateEditorGeometry(QWidget editor,const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;

mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H


#include <QMainWindow>
#include <QLabel>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include"qwcomboboxdelegate.h"
#include"qwfloatspindelegate.h"
#include"qwintspindelegate.h"
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;
   //定义3个代理类的实例变量
   QWIntSpinDelegate    intSpinDelegate; //整型数
   QWFloatSpinDelegate  floatSpinDelegate; //浮点数
   QWComboBoxDelegate   comboBoxDelegate; //列表选择


    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

qwcomboboxdelegate.h文件

#ifndef QWCOMBOBOXDELEGATE_H
#define QWCOMBOBOXDELEGATE_H


#include    <QItemDelegate>


class QWComboBoxDelegate : public QItemDelegate
{
    Q_OBJECT


public:
    QWComboBoxDelegate(QObject *parent=0);


//自定义代理组件必须继承以下4个函数
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const Q_DECL_OVERRIDE;


    void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const Q_DECL_OVERRIDE;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const Q_DECL_OVERRIDE;
};


#endif // QWCOMBOBOXDELEGATE_H

qwfloatspindelegate.h文件

#ifndef QWFLOATSPINDELEGATE_H
#define QWFLOATSPINDELEGATE_H


#include    <QObject>
#include    <QWidget>
#include    <QStyledItemDelegate>


class QWFloatSpinDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    QWFloatSpinDelegate(QObject *parent=0);


//自定义代理组件必须继承以下4个函数
//创建编辑组件
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const Q_DECL_OVERRIDE;


    void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const Q_DECL_OVERRIDE;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const Q_DECL_OVERRIDE;
};


#endif // QWFLOATSPINDELEGATE_H


qwintspindelegate.h文件

#ifndef QWINTSPINDELEGATE_H
#define QWINTSPINDELEGATE_H
#include<QStyledItemDelegate>


class QWIntSpinDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    QWIntSpinDelegate();
    //自定义代理组件必须继承一下四个函数,函数的原型都是固定的
    //创建编辑组件
    QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index)  const Q_DECL_OVERRIDE;
    //从数据模型获取数值
    void setEditorData(QWidget *editor,const QModelIndex &index) const Q_DECL_OVERRIDE;
    //将代理编辑器上的值更新给数据模型
    void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;
    //为代理组件设置合适的大小
    void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;


};


#endif // QWINTSPINDELEGATE_H

mainwindow文件

#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->tableView->setItemDelegateForColumn(0,&intSpinDelegate);  //测深,整数
    ui->tableView->setItemDelegateForColumn(1,&floatSpinDelegate);  //浮点数
    ui->tableView->setItemDelegateForColumn(2,&floatSpinDelegate); //浮点数
    ui->tableView->setItemDelegateForColumn(3,&floatSpinDelegate); //浮点数
    ui->tableView->setItemDelegateForColumn(4,&comboBoxDelegate); //comboBox选择型


    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";
    }
}

qwintspindelegate.cpp文件

#include "qwintspindelegate.h"
#include<QSpinBox>


QWIntSpinDelegate::QWIntSpinDelegate()
{


}
//创建代理编辑组件
QWidget *QWIntSpinDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                         const QModelIndex &index) const
{
    Q_UNUSED(index);
    Q_UNUSED(option);
    QSpinBox *editor=new QSpinBox(parent);
    editor->setFrame(false);//设置为无边框
    editor->setMaximum(10000);
    editor->setMinimum(0);
    return editor;//返回此编辑器


}
//从数据模型获取数据
void QWIntSpinDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  int value=index.model()->data(index,Qt::EditRole).toInt();
  QSpinBox *spinBox=static_cast<QSpinBox*>(editor);//类型转换
  spinBox->setValue(value);
}
//将代理编辑器上的值更新给数据模型
void QWIntSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QSpinBox *spinBox=static_cast<QSpinBox*>(editor);
    spinBox->interpretText();//如果值自上次说明以来发生了变化,它将发出信号
    int value=spinBox->value();
    model->setData(index,value,Qt::EditRole);
}
//设置组件大小
void QWIntSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                             const QModelIndex &index) const
{
    Q_UNUSED(index);
    editor->setGeometry(option.rect);//option的rect变量定义了单元格适合显示代理组建的大小
}


qwfloatspindelegate.cpp文件

#include "qwfloatspindelegate.h"


#include  <QDoubleSpinBox>


QWFloatSpinDelegate::QWFloatSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
{


}


QWidget *QWFloatSpinDelegate::createEditor(QWidget *parent,
   const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(index);
    Q_UNUSED(option);
    QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(0);
    editor->setDecimals(2);//设置小数位数为2
    editor->setMaximum(10000);


    return editor;
}


void QWFloatSpinDelegate::setEditorData(QWidget *editor,
                      const QModelIndex &index) const
{
    float value = index.model()->data(index, Qt::EditRole).toFloat();


    QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
    spinBox->setValue(value);
}


void QWFloatSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
    spinBox->interpretText();
    float value = spinBox->value();
    QString str=QString::asprintf("%.2f",value);


    model->setData(index, str, Qt::EditRole);
}


void QWFloatSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}


qwcomboboxdelegate.cpp文件

#include "qwcomboboxdelegate.h"


#include    <QComboBox>


QWComboBoxDelegate::QWComboBoxDelegate(QObject *parent):QItemDelegate(parent)
{


}


QWidget *QWComboBoxDelegate::createEditor(QWidget *parent,
       
                                          const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QComboBox *editor = new QComboBox(parent);
    //添加选项
    editor->addItem("A");
    editor->addItem("B");
    editor->addItem("C");
    editor->addItem("D");


    return editor;
}


void QWComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString str = index.model()->data(index, Qt::EditRole).toString();


    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentText(str);
}


void QWComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);


    QString str = comboBox->currentText();


    model->setData(index, str, Qt::EditRole);
}


void QWComboBoxDelegate::updateEditorGeometry(QWidget *editor,
                const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(index);
    editor->setGeometry(option.rect);
}

mainwindow.ui文件

在这里插入图片描述

运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/theRookie1/article/details/84954158
今日推荐