Qt5Demo-如何为QTableView创建自定义委托

SpinBox Delegate Example

这个例子介绍如何在model/view中为编辑控件创造一个定制的委托框架,带来达到将将标准的Qt输入控件嵌入到模型视图的效果
model/view开发矿建提供了一个标准的委托,我们在使用标准的视图控件中,会用到默认的委托,在大多数情况下编辑控件足够我们输入比如文本,布尔,或者其他简单的数据类型,然而,对于一些特殊的数据类型,有时候我们有必要使用定制的委托来编辑或者显示这些数据,或者使用定制的控件
Demo展示的窗口
本节中的思想将会在 Delegate 类中集中说明

SpinBoxDelegate Class的实现

关于此委托的实现如下

  class SpinBoxDelegate : public QStyledItemDelegate
  {
      Q_OBJECT

  public:
      SpinBoxDelegate(QObject *parent = nullptr);

      QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                            const QModelIndex &index) const override;

      void setEditorData(QWidget *editor, const QModelIndex &index) const override;
      void setModelData(QWidget *editor, QAbstractItemModel *model,
                        const QModelIndex &index) const override;

      void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                const QModelIndex &index) const override;
  };

Delegate 类仅仅声明了如下的函数,我么可以用这些函数来床架一个编辑控件窗口,并且将他们展示在一个现有的模型视图中,并且可以让他们和模型视图有关联,定制的委托也可以提供他们自己的painting code 通过重写paintEvent()函数,除此之外,还可以通过重写destroyEditor()函数来重用编辑控件窗口,这样的话,一个重用的窗口将会成为一个多态的对象,并在构造函数中创建,且在析构函数中被销毁。

SpinBoxDelegate Class的实现

委托通常是没有状态的,构造函数通常需要调用它的父类QObject的构造函数。

  SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
      : QStyledItemDelegate(parent)
  {
  }

因为这个委托是继承于QStyleItemDelegate类的,它检索到的模型的数据是以默认的方式展示在view中的,并且我们不需要提供一个定制的paintEvent()
createEditor函数返回一个编辑控件窗口,一个SpinBox限制了模型的数据输入唉0-100之间

  QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
                                         const QStyleOptionViewItem &/* option */,
                                         const QModelIndex &/* index */) const
  {
      QSpinBox *editor = new QSpinBox(parent);
      editor->setFrame(false);
      editor->setMinimum(0);
      editor->setMaximum(100);

      return editor;
  }

我们在Spinbox中添加了一个事件过滤器,这样可以确保它和其他的委托保持一致,他是通过基类的事件过滤器来实现的
setEditorData()函数从model中去取数据,并将其转变为int型数据,并且将它写入到编辑控件窗口中

  void SpinBoxDelegate::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);
  }

因为view处理的委托是源于QWidget格式的,所以我们不得不使用强制转换类型,这样我们才能得到SpinBox中的值
setModelData()函数,读取SpinBox中的值,并且将它写入到model中

  void SpinBoxDelegate::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);
  }

我们调用interpretText()函数,却表我们能够得到SpinBox中实时更新的值。
updateEditorGeometry()函数,更显用户编辑窗口的几何结构,通过使用style选项中的信息,下面的函数是在本例中需要做的做少的事情

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

更多的复杂 的编辑控件窗口可能需要使用option.rect类划分矩形窗口,如果有必要的话甚至需要包含一些子窗口

The main Function

这个例子和Qt提供的其他的例子有少许不同,为了在标准视图模型中去试验定制的编辑控件窗口,创建一个白喊预先定义的数据模型是非常有必要的
我们使用一种很普通的方法来创建这个应用,我们创建了一个包含一些数据的标准视图模型,然后创建了一个自定义委托用于编辑

  int main(int argc, char *argv[])
  {
      QApplication app(argc, argv);

      QStandardItemModel model(4, 2);
      QTableView tableView;
      tableView.setModel(&model);

      SpinBoxDelegate delegate;
      tableView.setItemDelegate(&delegate);

tableview被委托来通知,并且该view将会显示所有的对象,因为Delegate是QStyleItemDelegate的子类,因此每一个单元都设置成这样。
我们还插入了一下预先定义好的数据在模型中


      for (int row = 0; row < 4; ++row) {
          for (int column = 0; column < 2; ++column) {
              QModelIndex index = model.index(row, column, QModelIndex());
              model.setData(index, QVariant((row + 1) * (column + 1)));
          }
      }

最后,我们来展示这些数据

      tableView.setWindowTitle(QObject::tr("Spin Box Delegate"));
      tableView.show();
      return app.exec();
  }

github链接

https://github.com/chechem3/Delegate

VS源码

  • dlegate.h
#pragma once

#include <QStyledItemDelegate>

class delegate : public QStyledItemDelegate
{
	Q_OBJECT

public:
	delegate(QObject *parent);
	~delegate();

	QWidget* createEditor(QWidget* parent,
		const QStyleOptionViewItem& option,
		const QModelIndex& index) const override;

	void setEditorData(QWidget* editor, const QModelIndex& index) const override;
	void setModelData(QWidget* editor, QAbstractItemModel* model,
		const QModelIndex& index) const override;

	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option,
		const QModelIndex& index) const override;
};

  • delegate.cpp
//这个委托是一个允许用户使用一个Spinbox来改变
//model里面的数值

#include "delegate.h"
#include <qspinbox.h>

delegate::delegate(QObject *parent)
	: QStyledItemDelegate(parent)
{
}

delegate::~delegate()
{
}

QWidget* delegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QSpinBox* editor = new QSpinBox(parent);
	editor->setFrame(false);
	editor->setMinimum(0);
	editor->setMaximum(100);
	return editor;
}

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

	QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
	//关于static_cast:属于C语言的强制数据类型转换,相当于把editor转变为QSpinBox*

	spinBox->setValue(value);
}

void delegate::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 delegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	editor->setGeometry(option.rect);
}
  • spinboxdelegate
#pragma once

#include <QtWidgets/QWidget>
#include <qstandarditemmodel.h>
#include "ui_spinboxdeleget.h"
#include "delegate.h"

class spinboxdeleget : public QWidget
{
	Q_OBJECT

public:
	spinboxdeleget(QWidget *parent = Q_NULLPTR);

private:
	Ui::spinboxdelegetClass ui;
	QStandardItemModel model;
	delegate * delegate_1;
	
};

  • spinboxdelegate.capp
#include "spinboxdeleget.h"
#include "delegate.h"

spinboxdeleget::spinboxdeleget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	//QStandardItemModel model(4, 2);
	model.setColumnCount(2);
	model.setRowCount(4);

	ui.tableView->setModel(&model);

	//delegate delegate_1(nullptr);
	delegate_1 = new delegate(NULL);
	ui.tableView->setItemDelegate(delegate_1);

	ui.tableView->horizontalHeader()->setStretchLastSection(true);
	//setStretchLastSection:这个属性决定了在模型头中最后一个有效的部分
	//是否占用有效的空间,默认的设置值是否

	//由QTreeView提供的水平的头部分如果通过这个设置变为真,则这个View不会浪费任何
	//头的空间

	for (int row = 0; row < 4; ++row) {
		for (int column = 0; column < 2; ++column) {
			QModelIndex index = model.index(row, column, QModelIndex());
			model.setData(index, QVariant((row + 1) * (column + 1)));
		}
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值