QT-delegate

        这章联练习了QT里的代理。之前学习IOS,MVC是一个很主要的框架。该框架主要将数据、视图、控制器分开。以实现面向对象高内聚、低耦合的特点。
        QT里的MV,这里没有了控制器。MVC的原理是控制器控制model,去显示在view上。但model和view之间是互相不交互的。所以在QT里既然没有了控制器,
        那么model与view之间是怎么交互的呢?
       在QT中,把view和controller合在一起。本质上是将model与绑定在一起。省略了控制的那个过程。并引入了delegate的概念。这里的delegate是将所有与数据编辑或定制显示相关的操作都由它处理。model不存储数据,而是为View与delegate访问数据提供标准的接口。model都会以数据表项的方式进行管理。


接下来以我写的代码为例,做以分析:

 part1:视图部分

    QStandardItemModel model(4,4);

    QTableView  tableView;
    tableView.setModel(&model);

    dateDelegate datedelegate;
    ComboboxDelegate combbDelegate;
    SpinBoxDelegate spinDelegate;

    tableView.setItemDelegateForColumn(1,&datedelegate);
    tableView.setItemDelegateForColumn(2,&combbDelegate);
    tableView.setItemDelegateForColumn(3,&spinDelegate);
    //View的setItemDelegateForColumn()函数为指定的列应用指定的Delegate
    
    model.setHeaderData(0,Qt::Horizontal,QObject::tr("Name"));
    model.setHeaderData(1,Qt::Horizontal,QObject::tr("Birthday"));
    model.setHeaderData(2,Qt::Horizontal,QObject::tr("job"));
    model.setHeaderData(3,Qt::Horizontal,QObject::tr("Income"));

 QStandardItemModel model(4,4);

//定义了一个4×4的model,这里的model类型是QStandardItemModel,用于存储定制数据的通用模型

 声明了一个表视图,并将视图与刚才的model绑在一起。
 声明三个代理。
 并给该表格的第几列设置不同的代理,以完成不同的功能。
 view的setItemDelegateForColumn()函数为指定的列设置代理。

part2:文件部分

 QFile file("/home/qinhuan/QT/QT_test/Delegate/data.txt");

    if(file.open(QFile::ReadOnly))
    {
        QTextStream stream(&file);
        QString line;
        int row = 0;
        do{
                line=stream.readLine();
                if(!line.isEmpty())
                {
                        QStringList pieces = line.split(",",QString::SkipEmptyParts);
                        model.setData(model.index(row,0,QModelIndex()),pieces.value(0));
                        model.setData(model.index(row,1,QModelIndex()),pieces.value(1));
                        model.setData(model.index(row,2,QModelIndex()),pieces.value(2));
                        model.setData(model.index(row,3,QModelIndex()),pieces.value(3));

                        row++;
                }
        }while (!line.isEmpty());
        file.close();
    }

打开文件,给model。
这里的文件我使用了绝对路径能打开,使用相对路径就会找不到?
QStringList pieces = line.split(",",QString::SkipEmptyParts);
文件里的一行数据使用‘,’分割开,使用split函数将字符串分开,放入字符串数列中。
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
model.setData(model.index(row,0,QModelIndex()),pieces.value(0));//将字符串数组的数据赋给model相对应的位置。
part3:代理部分
       在main函数里已经将视图 数据 模型已经建好,并能正常的显示。那代理部分需要做什么呢?
       比如你在已经建好的视图上更改了某一项的数据,则需要通过代理然后更新模型里的数据,起一个编辑和渲染的作用。模型里到底存不存数据?
       在新建一个代理类时,需要继承于QItemDelegate,这样可以使用它提供的四个函数的默认实现,必须这样子,要不然会出现下面这种错误:
/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qabstractitemview.h:207: note:   no known conversion for argument 2 from 'ComboDelegate*' to 'QAbstractItemDelegate*'

需要重写的四个方法是这些:

QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const
    //返回一个编辑控件,比如在视图里这块你需要对combobox里的数据进行处理,则需要重新定义一个combobox,并且继承于父类
    //并在该控件上安装事件过滤器,使得代理能捕捉到该对象的事件。
    combobox->installEventFilter(const_cast<ComboboxDelegate *>(this));

   在combobox安装事件过滤器,要把当前的this指针转换成combobox代理指针型的,所以可以推断出this是变量指针,因为const_cast是不能修改常量的值

void setEditorData(QWidget *editor, const QModelIndex &index) const;
    //更新delegate控件的数据显示
    index->model()->data(index).toString   //获取指定的index数据项的数据,调用QModelIndex的model()可获得提供此index的model对象,data()
    函数返回的是QVariant对象,把它转换成一个QString类型数据  
    拿到moedl的数据,把editor转换成要用到的控件,再将数据放在控件上
  
 void setModelData(QWidget *editor, QAbstractItemModel *model,
                       const QModelIndex &index) const;
//若更改了view视图上的数据,则需要通过代理来更该model的数据。
//先将editor转换成所需控件,获得控件上的数据
//再将该数据转给model
  
 void updateEditorGeometry(QWidget *editor,
         const QStyleOptionViewItem &option, const QModelIndex &index) const;
代码:https://github.com/Jelly-123/QT/tree/master/Delegate



阅读更多
上一篇QT-键盘事件
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭