十三、自定义代理类的实现
1)基于QSpinBox的自定义代理类的实现
1、createEditor()函数的实现
createEditor函数是用于创建需要的编辑组件,此类我们选用QSpinBox作为编辑组件,函数实现:
QWidget* QWIntSpinDelegate::createEditor(QWidget * parent,const QStyleOptionViewItem &option,const QModelIndex &index)const
{
//创建编辑组件
QSpinBox * spinEditor = new QSpinBox(parent);
spinEditor->setFrame(false);//设置为无边框
spinEditor->setMinimum(0);
spinEditor->setMaximum(10000);
return spinEditor;//返回此编辑器
}
这个新创建的编辑组建爱你spinEditor,parent只想试图组建,然后对编辑组件做了一些基本设置,将其返回。
2、setEditorDate()函数的实现
setEditorData函数用于从数据模型获取数值,设置为编辑器的显示值,当双击一个单元格进入编辑状态时,就会自动调用这个函数:
void setEditorDate(QWidget *editor,const QModelIndex &index)const
{
//从数据模型获取数值,显示到代理组件中
int value = index.model()->data(index,Qt::EditorRole).toInt();
QSpinBox * spinBox= static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
函数传递来的参数editor只想代理编辑组件,index是关联的数据单元的模型索引,通过强制类型转换将editor转换为QSpinBox类型组件spinBox,然后将获取的数值设置为spinBox的显示值。
3、setModelData()函数的实现
setModelData函数用于将代理编辑器上的数值更新给数据模型,当用户在界面上完成编辑时就是调用此函数,将界面上的数据更新到数据模型:
void QWIntSpinDelegate::setModelDate(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index)const
{
//将代理组件的数据保存到数据模型中
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setDate(index,value,Qt::EditRole);
}
程序先获取代理组件编辑器里的数值,然后利用传递来的数据模型model和模型索引index将编辑器的最新值更新到数据模型里。
4、updateEditorGeometry()函数的实现
updateEditorGeometry函数用于为代理组件设置一个合适的大小,函数传递的参数option的rect变量定义了单元格适合显示代理组件的大小,直接设置为此值即可。
void QWIntSpinDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index)const
{
//设置组件大小
editor->setGeometry(option.rect);
}
2) 自定义代理类的使用
在主窗口类中定义自定义代理类的实例变量:
class MainWindow:public QMainWindow
{
private:
QWIntSpinDelegate intSpinDlegate;//整形数
QWFloatSpinDelegate floatSpinDelegate;//浮点数
}
在MainWindow的构造函数中,为tableView的某些列设置自定义代理组件:
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);
theModel = new QStandardItemModel(2,FixedColumnCount,this);
theSelection = new QItemSelectionmodel(theModel);//选择模型
connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
ui->tableView->setModel(theModel);//设置数据模型
ui->tableView->setSelectionModel(theSelection);//设置选择模型
//为各列设置自定义代理组件
//ui->tableView->setItemDelegateForColumn(0,&intSpinDelegate);//测深,这行会报错
ui->tableView->setItemDelegateForColumn(0,new QWIntSpinDelegate(this));//改成这样就不报错了
//...
}
这样增加了自定义代理功能后,在编辑“测深”列时,会在单元格的位置出现一个SpinBox组件,用于输入整数;在编辑浮点数的列时,会出现一个FloatSpinBox的组件,用于输入浮点数。
3)setItemDelegateForColumn()函数的使用注意
注意设置委托的方式,在找资料的过程中看到的都以如下使用方式:
doubleDelegate double_delegate;
ui->tableView->setItemDelegateForColumn(2, &double_delegate);
但程序会报错,改成使用 new 的方式后正常。
来自链接: 链接: QtableView委托的使用setItemDelegateForColumn()
原因:因为,一个委托只能对应到一个视图,因为delegate在收到closeEditor的信号的时候,可能会重复关闭已经关闭的editor
修改代码后,记得清楚项目路径下的build文件夹,然后再重新构建,这个时候之前出现的一些问题才会被重新解决