赞
踩
QT属性表支持设置的属性时根据QVariant确定的,但是qt属性表并没有为每一种QVariant类型实现一种属性管理器。
下面来实现一种类型:选择图片文件。
选择一张图片并将地址显示到属性表里。
实现的过程如下:
定义一种新类型:UserType_FileName
查看QVariant的头文件里这里告诉你可以自定义类型只要类型的值不超过0xffffffff就没问题。
那么这里定义类型UserType_FileName的值为:QVariant::UserType + 1
定义类型UserType_FileName的管理器名称为:QtUserType_FileNameManager
在属性表的这个文件里找个位置定义类。
class QtUserType_FileNameManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtUserType_FileNameManager: public QtAbstractPropertyManager { Q_OBJECT public: QtUserType_FileNameManager(QObject *parent = nullptr); ~QtUserType_FileNameManager(); public Q_SLOTS: void setValue(QtProperty *property, QString val); QString value(const QtProperty *property) const; Q_SIGNALS: void valueChanged(QtProperty *property, QString fileName); protected: virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); QString valueText(const QtProperty *property) const; private: friend class QtProperty; QtUserType_FileNameManagerPrivate * d_ptr; Q_DECLARE_PRIVATE(QtUserType_FileNameManager) Q_DISABLE_COPY(QtUserType_FileNameManager) };
QtUserType_FileNameManager::QtUserType_FileNameManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtUserType_FileNameManagerPrivate; d_ptr->q_ptr = this; } QtUserType_FileNameManager::~QtUserType_FileNameManager() { clear(); delete d_ptr; } void QtUserType_FileNameManager::setValue(QtProperty *property, QString val) { const QtUserType_FileNameManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtUserType_FileNameManagerPrivate::Data data = it.value(); if (data.val == val) return; data.val = val; it.value() = data; emit propertyChanged(property); emit valueChanged(property, data.val); } QString QtUserType_FileNameManager::value(const QtProperty *property) const { return getValue<QString>(d_ptr->m_values, property); } void QtUserType_FileNameManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtUserType_FileNameManagerPrivate::Data(); } void QtUserType_FileNameManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } QString QtUserType_FileNameManager::valueText(const QtProperty *property) const { const QtUserType_FileNameManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return it.value().val; }
class QtUserType_FileNameManagerPrivate { QtUserType_FileNameManager * q_ptr; Q_DECLARE_PUBLIC(QtUserType_FileNameManager) public: QtUserType_FileNameManagerPrivate() { } struct Data { Data() { } QString val; }; typedef QMap<const QtProperty *, Data> PropertyValueMap; QMap<const QtProperty *, Data> m_values;//一个管理器管理着多个UserType_FileName类型的属性 };
qt源码都是用q指针和d指针的方式,数据放在d指针指向的私有对象里。
注意valueText()函数返回的内容是属性表里显示的内容,若没有实现这个函数则属性表里不会显示内容。
然后是自定义属性类型的工厂类
首先定义一个控件,作为点击时修改属性内容的控件:
class QtUserType_FileNameWidget : public QWidget { Q_OBJECT public: QtUserType_FileNameWidget(QWidget * parent); void setValue(const QString &value); Q_SIGNALS: void valueChanged(const QString &value); private Q_SLOTS: void buttonClicked(); private: QLabel *m_label; QToolButton *m_button; QString filePath; }; QtUserType_FileNameWidget::QtUserType_FileNameWidget(QWidget * parent) : QWidget(parent), m_label(new QLabel), m_button(new QToolButton) { QHBoxLayout *lt = new QHBoxLayout(this); setupTreeViewEditorMargin(lt); lt->setSpacing(0); lt->addWidget(m_label); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(60); setFocusProxy(m_button); setFocusPolicy(m_button->focusPolicy()); m_button->setText(tr("选择图片")); m_button->installEventFilter(this); connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); lt->addWidget(m_button); this->setLayout(lt); } void QtUserType_FileNameWidget::setValue(const QString &c) { if (filePath != c) { filePath = c; m_label->setText(c); } } void QtUserType_FileNameWidget::buttonClicked() { QString filePath = QFileDialog::getOpenFileName(this,tr("打开图片文件"),QDir::currentPath(),QString("Image File(*.bmp *.jpg *.jpeg *.png)")); if(filePath.isEmpty()) { return; } if (filePath != this->filePath) { setValue(filePath); emit valueChanged(filePath); } }
这里定义一个QWidget包含一个QLabel显示打开的文件名称,和一个工具按钮,点击弹出弹窗选择图片。定义在:
属性工厂:
class QtUserType_FileNameFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtUserType_FileNameFactory :public QtAbstractEditorFactory<QtUserType_FileNameManager> { Q_OBJECT public: QtUserType_FileNameFactory(QObject *parent = nullptr); ~QtUserType_FileNameFactory(); protected: void connectPropertyManager(QtUserType_FileNameManager *manager); QWidget *createEditor(QtUserType_FileNameManager *manager, QtProperty *property,QWidget *parent); void disconnectPropertyManager(QtUserType_FileNameManager *manager); private: QtUserType_FileNameFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtUserType_FileNameFactory) Q_DISABLE_COPY(QtUserType_FileNameFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QString &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QString &)) };
QtUserType_FileNameFactory::QtUserType_FileNameFactory(QObject *parent) : QtAbstractEditorFactory<QtUserType_FileNameManager>(parent), d_ptr(new QtUserType_FileNameFactoryPrivate()) { d_ptr->q_ptr = this; } QtUserType_FileNameFactory::~QtUserType_FileNameFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } void QtUserType_FileNameFactory::connectPropertyManager(QtUserType_FileNameManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty*,QString)),this, SLOT(slotPropertyChanged(QtProperty*,QString))); } void QtUserType_FileNameFactory::disconnectPropertyManager(QtUserType_FileNameManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty*,QString)), this, SLOT(slotPropertyChanged(QtProperty*,QString))); } QWidget *QtUserType_FileNameFactory::createEditor(QtUserType_FileNameManager *manager, QtProperty *property, QWidget *parent) { QtUserType_FileNameWidget *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, SIGNAL(valueChanged(QString)), this, SLOT(slotSetValue(QString))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; }
class QtUserType_FileNameFactoryPrivate : public EditorFactoryPrivate<QtUserType_FileNameWidget> { QtUserType_FileNameFactory *q_ptr; Q_DECLARE_PUBLIC(QtUserType_FileNameFactory) public: void slotPropertyChanged(QtProperty *property, const QString &value); void slotSetValue(const QString &value); }; void QtUserType_FileNameFactoryPrivate::slotPropertyChanged(QtProperty *property,const QString &value) { const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); if (it == m_createdEditors.end()) return; QListIterator<QtUserType_FileNameWidget *> itEditor(it.value()); while (itEditor.hasNext()) itEditor.next()->setValue(value); } void QtUserType_FileNameFactoryPrivate::slotSetValue(const QString &value) { QObject *object = q_ptr->sender(); const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtUserType_FileNameManager *manager = q_ptr->propertyManager(property); if (!manager) { return; } manager->setValue(property, value); return; } } }
这些定义都是大同小异的,基本上是复制其他类型的定义然后改改类名称。
定义完成,接下来是使用。
QtUserType_FileNameManager添加到QtVariantPropertyManager:
QtUserType_FileNameManager * userType_FileNameManager = new QtUserType_FileNameManager(this);
d_ptr->m_typeToPropertyManager[QVariant::UserType + 1] = userType_FileNameManager;
d_ptr->m_typeToValueType[QVariant::UserType + 1] = QVariant::String;
connect(userType_FileNameManager, SIGNAL(valueChanged(QtProperty *, QString)),
this, SLOT(slotValueChanged(QtProperty *, QString)));
自定义的属性里面的值是打开文件选择的图片路径,也就是QString类型。
在以下地方把新类型添加上:
connectPropertyManager()函数:
disconnectPropertyManager()函数:
qtvariantproperty.cpp文件中 QtVariantEditorFactory构造函数:
d_ptr->m_picFileNameFactory = new QtUserType_PicFileNameFactory(this);
d_ptr->m_factoryToType[d_ptr->m_picFileNameFactory] = QVariant::UserType + 1;
d_ptr->m_typeToFactory[QVariant::UserType + 1] = d_ptr->m_picFileNameFactory;
到这新增自定义属性类型管理器完成。使用:
————————————————
原文链接:https://blog.csdn.net/kenfan1647/article/details/110952990
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。