Qt5Demo-如何创建QColorFactory
Color Editor Factory Example
本例程展示了了如何使用QItemDelegate来创建一个编辑控件
当我们在QListView, QTableView,或者QTreeView中编辑数据时,编辑控件是通过委托来创建和显示的,QItemDelegate是Qt自己的一个默认的Item View,我们可以使用QItemEditorFactory来创造一个编辑控件,一个独立的由QItemEditorFactory创建的实例默认被用在所有的委托上。
一个 item editor factory 包含了一系列的QItemEditorCreatorBase的实例,QItemEditorC热at而是一个专业的生产编辑控件的工厂,他可以提供针对一种QVariant数据类型的专门的编辑控件(所有的在Qt中储存的模型都存放的是QVariant类型的数据),一个编辑控件可以是任何Qt或者其他的widget。
在这个例程中,我们创造了一个编辑控件(在ColorListEditor 类中实现),它可以编辑QColor的数据类型,且通过QitemDelegates来使用,我们要做的是通过创建一个新的QItemEditorCreatorBase,并使用它来生产ColorListEditors,并且把它登记为一个新的工厂,随后我们把这个工厂设置为默认的item编辑工厂(唯一的工厂实例),为了测试我们的编辑器,我们把它应用在一个Window类中,他可以把这个编辑控件应用在一个QTableWidget中,然后我们就可以使用这个控件来设置QColor
Window Class 的实现
在window类中,我们针对我们的color editor创建了一个item编辑控件并且将它添加到默认的工厂中,我们同样创造了一个QTableWidget,来测试我们的编辑控件,他将会存放一些数据并且显示在window中。
我们来进一步看看代码:
Window::Window()
{
QItemEditorFactory *factory = new QItemEditorFactory;
QItemEditorCreatorBase *colorListCreator =
new QStandardItemEditorCreator<ColorListEditor>();
factory->registerEditor(QVariant::Color, colorListCreator);
QItemEditorFactory::setDefaultFactory(factory);
createGUI();
}
QStandarditemEditorCrator是一个继承于 QItemEditorCreatorBase的实例类,它的构造函数中有一个模板类,在这个类中,所有的实例都是由createWidget()返回的,这个creator使用一个构造函数,并将QWidget作为它唯一的参数,这个模板类必须提供这些,这样,我们就不需要一个QStandardItemEditorCreator的子类了。
在这个工厂设置以后,所有标准的item委托都会用它(尽管有的委托是在这个工厂创造之前创造的)
createGUI()函数设置table并且将数据填写到里面
ColorListEditor定义
ColorListEditor继承于QComboBox并且允许用户去在下拉菜单中选择QColor
class ColorListEditor : public QComboBox
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor USER true)
public:
ColorListEditor(QWidget *widget = nullptr);
public:
QColor color() const;
void setColor(const QColor &color);
private:
void populateList();
};
QItemDelegate 负责控制编辑控件和模型,比如它从model中检索数据,且从model中的编辑控件中储存数据,一个编辑控件它编辑的数据储存在这个编辑控件的用户数据属性中,且它的委托使用Qt的属性系统通过名称来访问它,我们使用Q_PROPERTY宏来声明我们的数据属性,这个属性通过USER关键词被设置成为用户类型。
ColorListEditor 的实现
在ColorListEditor的构造函数中,我们只调用populateList()这个函数,这个我们后面再谈,我们先看Color()函数
QColor ColorListEditor::color() const
{
return qvariant_cast<QColor>(itemData(currentIndex(), Qt::DecorationRole));
}
We return the data that is selected in the combobox. The data is stored in the Qt::DecorationRole as the color is then also displayed in the popup list (as shown in the image above).
void ColorListEditor::setColor(const QColor &color)
{
setCurrentIndex(findData(color, Qt::DecorationRole));
}
The findData() function searches the items in the combobox and returns the index of the item that has color in the Qt::Decoration role.
void ColorListEditor::populateList()
{
const QStringList colorNames = QColor::colorNames();
for (int i = 0; i < colorNames.size(); ++i) {
QColor color(colorNames[i]);
insertItem(i, colorNames[i]);
setItemData(i, color, Qt::DecorationRole);
}
}
Qt通过名称可以知道一些预先定义的颜色,我们仅仅通过轮询的方式来添加到我们的编辑控件中
Further Customization of Item View Editors
你可以定制Qt的模型显示框架通过多种方式,在这个实例中展示的程序可以展示定制的编辑控件,更多的定制化可以通过对QItemEditorFactory和QItemEditorCreaterBase这两个类进行派生,也可以通过对QItemDelegate类进行派生,如果你想使用工厂模式来创建的话
一些建议:
- 如果编辑控件窗口用户没有对其进行事前定义,委托将会使用它的属性名称对工厂进行询问,在这种情况下,你可以使用QItemEditorCreator类,他会使用属性名进行编辑。作为构造函数的依据。
- 如果编辑控件需要其他的构造函数或者初始化函数而不是由QItemEditorCreatorBase来提供,一定要重用QItemEditorCreatorBase::createWidget().
- 你也可以对QItemEditorFactory进行派生,如果你仅仅想针对特定的数据类型提供一个编辑控件,或者使用其他的创造编辑控件的方法。
在这个例子中,我们使用了标准的QVariant数据类型,你也可以使用其他的数据类型,在StarDelegateExample中,我们展示了如何在QVariant中储存其他的数据类型,并且绘制编辑这个类继承于QItemDelegate。
github链接
https://github.com/chechem3/tableview_add_combox
代码
- ColorListEditor.h
#pragma once
#include <QComboBox>
QT_BEGIN_NAMESPACE
class QColor;
class QWidget;
QT_END_NAMESPACE
class ColorListEditor : public QComboBox
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor USER true)
public:
ColorListEditor(QWidget *parent);
~ColorListEditor();
public:
QColor color() const;
void setColor(const QColor &color);
private:
void populateList();
};
- ColorListEditor.cpp
#include "ColorListEditor.h"
#include <qwidget.h>
ColorListEditor::ColorListEditor(QWidget *parent)
: QComboBox(parent)
{
populateList();
}
ColorListEditor::~ColorListEditor()
{
}
QColor ColorListEditor::color() const
{
return qvariant_cast<QColor>(itemData(currentIndex(), Qt::DecorationRole));
//qvariant_cast<T>(const QVariant &value)这个函数功能是将value转换为<T>
//Qt::DecorationRole是QT的命名空间中的一个枚举变量,每一个在model中的item
//都有一个关联数据的单元的设置,每一个都有自己的角色,这个角色被view用来表明
//model中的何种类型的data数据是需要的,定制的模型需要返回如下类型的数据
//预先定义的角色(和关联类型)如下::可以看官方的Qt名称空间的定义
}
void ColorListEditor::setColor(const QColor & color)
{
setCurrentIndex(findData(color, Qt::DecorationRole));
//设置选中的combox index
}
void ColorListEditor::populateList()
{
const QStringList colorNames = QColor::colorNames();
//QColor::colorNames()里面包含了预先定义的颜色列表
for (int i = 0; i < colorNames.size(); i++) {
QColor color(colorNames[i]);
insertItem(i, colorNames[i]);
setItemData(i, color, Qt::DecorationRole);
}
}
- Window.h
#pragma once
#include <QtWidgets/QWidget>
#include "ui_Window.h"
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = Q_NULLPTR);
private:
Ui::WindowClass ui;
void creatGUI();
};
- Window.cpp
#include "Window.h"
#include "ColorListEditor.h"
#include <qitemeditorfactory.h>
#include <qvector.h>
#include <qwidget.h>
#include <QTableWidgetItem>
Window::Window(QWidget *parent)
: QWidget(parent)
{
//ui.setupUi(this);
QItemEditorFactory *factory = new QItemEditorFactory;
//QItemEditorFactory类提供了一个用来编辑在view和代理中的item数据
//当我们在itemview中通过委托编辑和显示数据时,QStyledItem是一个默认安装在Qt的
//item view中的委托,我们使用QItemEditorFactory类来创一个关于它的一个编辑
//原来有一个默认的编辑,如果用户新建编辑的话,将会替代原来的规则
//当我们需要自定义view的规则的时候,可以考虑使用这种方式来编辑
QItemEditorCreatorBase *colorListCreator =
new QStandardItemEditorCreator<ColorListEditor>;
//QItemEditorCreatorBase类提供了一个抽象的基类,当我们创建item editor creators
//的时候必须派生出新的子类
factory->registerEditor(QVariant::Color, colorListCreator);
//registerEditor::注册一个item editor creator通过QItemEditorCreatorBase
//指定的用户需要的数据格式
QItemEditorFactory::setDefaultFactory(factory);
//设置默认的编辑factory通过给定的factory
ui.setupUi(this);
creatGUI();
}
void Window::creatGUI()
{
const QVector<QPair<QString, QColor>> list =
{
{tr("Alice"), QColor("aliceblue")},
{tr("Neptun"), QColor("aquamarine")},
{tr("Ferdinand"), QColor("springgreen")}
};
//QPair::是一个可以储存成对数据的模板类
ui.tableWidget->setRowCount(3);
ui.tableWidget->setColumnCount(2);
ui.tableWidget->setHorizontalHeaderLabels({ tr("Name"), tr("Hair Color") });
ui.tableWidget->verticalHeader()->setVisible(false);
ui.tableWidget->resize(150, 50);
//setHorizontalHeaderLabels::设置横向头标签
//verticalHeader()::指向纵向头,然后设置消失
for (int i = 0; i < 3; i++) {
const QPair<QString, QColor> &pair = list.at(i);
QTableWidgetItem *nameItem = new QTableWidgetItem(pair.first);
QTableWidgetItem *colorItem = new QTableWidgetItem;
colorItem->setData(Qt::DisplayRole, pair.second);
//这是使用了setdata的按照role的方式去添加data的方式
ui.tableWidget->setItem(i, 0, nameItem);
ui.tableWidget->setItem(i, 1, colorItem);
}
ui.tableWidget->resizeColumnToContents(0);
//resizeColumnToContents::按照给定的委托设置去重新绘制/调整列
ui.tableWidget->horizontalHeader()->setStretchLastSection(true);
//setStretchLastSection::这个属于tableview的横轴头的设置,设置为true
//后,最后一列的头文件将会无限延伸
setWindowTitle(tr("Color Editor Factory"));
}