当前位置:   article > 正文

QT属性表控件:新增自定义属性类型_qtpropertybrowser自定义

qtpropertybrowser自定义

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)
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
 
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
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类型的属性
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

这里定义一个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 &))
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
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;
        }
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

这些定义都是大同小异的,基本上是复制其他类型的定义然后改改类名称。

定义完成,接下来是使用。

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)));
  • 1
  • 2
  • 3
  • 4
  • 5

自定义的属性里面的值是打开文件选择的图片路径,也就是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;
  • 1
  • 2
  • 3

到这新增自定义属性类型管理器完成。使用:
在这里插入图片描述

————————————————

原文链接:https://blog.csdn.net/kenfan1647/article/details/110952990

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/115115
推荐阅读
相关标签
  

闽ICP备14008679号