QtnProperty是一个开源的第三方Qt库,参考下面连接地址能够下载最新的版本。
git:https://github.com/lexxmark/QtnPropertygit
基础使用说明,以Qt5.8.0mingw开发环境为例:github
目录Core和PropertyWidget是须要编译的两个静态库,将其编译后会在bin-win目录下生成libQtnPropertyCore.a和libQtnPropertyWidget.a两个静态连接库,注意的是config.pri中已经指定了目标路径,若是须要改变生成路径,请在config.pri中修改,一样的,其余全部的子项目都应该包含这个文件,方便将全部的生成文件都放到同一个地方;windows
在本身的项目*.pro中,包含下面代码:app
include(../Config.pri) include(../QtnProperty.pri)
这里将config.pri包含进来正如前面说的是要将exe程序和.a库文件生成到同一个地方,引入QtnProperty.pri相似于VC中的库头文件同样。而后将库文件打包到pro配置文件:ide
INCLUDEPATH += $$PWD/../Core INCLUDEPATH += $$PWD/../PropertyWidget DEPENDPATH += $$PWD/../PropertyWidget DEPENDPATH += $$PWD/../CorelibQtnPropertyCore.a CONFIG(debug, debug|release): LIBS += $$PWD/../bin-win/libQtnPropertyCore.a CONFIG(debug, debug|release): LIBS += $$PWD/../bin-win/libQtnPropertyWidget.a
到此就能够编译和使用QtnProperty库的啦!函数
在使用以前,须要先调用initQtnPropertyWidgetLibrary()这个函数,在PropertyDelegateFactory中声明。进入这个函数能够看到,该函数主要是注册属性项的代理类,若是想了解每一个属性项是如何实现的,能够查看其中的实现。好比打开regBoolDelegates()这个函数:ui
void regBoolDelegates() { QtnPropertyDelegateFactory::staticInstance() .registerDelegateDefault(&QtnPropertyBoolBase::staticMetaObject , &qtnCreateDelegate<QtnPropertyDelegateBoolCheck, QtnPropertyBoolBase> , "CheckBox"); QtnPropertyDelegateFactory::staticInstance() .registerDelegate(&QtnPropertyBoolBase::staticMetaObject , &qtnCreateDelegate<QtnPropertyDelegateBoolCombobox, QtnPropertyBoolBase> , "ComboBox"); }
能够看到对于bool类型,提供了两个不一样的实现,一种是CheckBox,一种是ComboBox,默认是CheckBox实现。若是须要本身实现,能够参考QtnPropertyDelegateBoolCheck的代码,仿照实现便可。若是须要选择ComboBox来实现bool,能够在代码中这样写:this
auto boolValue = new QtnPropertyBool(propertySet); QtnPropertyDelegateInfo boolNewDelegate; boolNewDelegate.name = "ComboBox"; boolValue->setDelegate(boolNewDelegate);
再看regIntDelegates()这个函数,提供了SpinBox和SliderBox两个代理类实现:spa
void regIntDelegates() { QtnPropertyDelegateFactory::staticInstance() .registerDelegateDefault(&QtnPropertyIntBase::staticMetaObject , &qtnCreateDelegate<QtnPropertyDelegateInt, QtnPropertyIntBase> , "SpinBox"); QtnPropertyDelegateFactory::staticInstance() .registerDelegate(&QtnPropertyIntBase::staticMetaObject , &qtnCreateDelegate<QtnPropertyDelegateSlideBoxTyped<QtnPropertyIntBase>, QtnPropertyIntBase> , "SliderBox"); }
咱们进入QtnPropertyDelegateInt这个代理类,发现全部的代理类其实都实现了两个接口:debug
QWidget* QtnPropertyDelegateInt::createValueEditorImpl(QWidget* parent, const QRect& rect, QtnInplaceInfo* inplaceInfo) { QSpinBox* spinBox = new QSpinBox(parent); spinBox->setGeometry(rect); new QtnPropertyIntSpinBoxHandler(owner(), *spinBox); if (inplaceInfo) { spinBox->selectAll(); } return spinBox; } bool QtnPropertyDelegateInt::propertyValueToStrImpl(QString& strValue) const { strValue = QString::number(owner().value()); return true; }
这里最主要的实现就是这个createValueEditorImpl()函数了,能够看到SpinBox和SliderBox的区别也就主要在于建立的窗口不同。一样,若是想提供ComboBox来实现下拉选择呢?固然也是同样的,仿照这个类,写一个相似的代理接口类,在这个函数中实现combobox来选择数据,那么问题来了?ComboBox中的数据如何提供?接下来看一个已经实现好的数据选择类QtnPropertyDelegateIntList,如何将ComboBox中的数据传递进去,实现代码:
QWidget* QtnPropertyDelegateIntList::createValueEditorImpl(QWidget* parent, const QRect& rect, QtnInplaceInfo* inplaceInfo) { if (owner().isEditableByUser()) { QComboBox *comboBox = new QComboBox(parent); auto delegate = owner().delegate(); if (delegate) { QList<int> values; qtnGetAttribute(delegate->attributes, "values", values); for (auto value : values) { comboBox->addItem(QString::number(value), value); } } comboBox->setGeometry(rect); // connect widget and property new QtnPropertyIntComboBoxHandler(owner(), *comboBox); if (inplaceInfo) comboBox->showPopup(); return comboBox; } else { QLineEdit *lineEdit = new QLineEdit(parent); lineEdit->setReadOnly(true); lineEdit->setText(QString::number((int)owner())); lineEdit->setGeometry(rect); return lineEdit; } }
代码已经很清晰了,请注意看这两行:
QList<int> values;
qtnGetAttribute(delegate->attributes, "values", values);
建立ComboBox以后,从一个叫作delegate->attributes的属性中获取到QList<int>,而后将其加入到ComboBox中,这个delegate是一个QtnPropertyDelegateInfo类,这就是前面bool属性设置代码时用到的QtnPropertyDelegateInfo类,它除了有name属性外,还有一个attributes属性,支持QVariant类型,能够将任意类型的变量传递过去。当咱们不知道如何传递属性参数时,就能够找到代理类,找到createValueEditorImpl()函数,看看中间究竟使用到了那些属性变量。在这里只须要传递一个QList<int>就能够了:
QList<int> list; for (auto i=0; i<10; i++) { list.append(i); } QtnPropertyDelegateInfo deleInfo; deleInfo.name = "IntList"; deleInfo.attributes.insert("values", QVariant::fromValue(list)); intValue->setDelegate(deleInfo);
#include "widget.h" #include "ui_widget.h" #include "PropertySet.h" #include "PropertyCore.h" #include "PropertyBase.h" #include "Core/GUI/PropertyButton.h" #include "Core/GUI/PropertyQBrush.h" #include "Core/GUI/PropertyQColor.h" #include "Core/GUI/PropertyQFont.h" #include "Core/GUI/PropertyQPen.h" #include <QMessageBox> #include <QVector> #include <QFileDialog> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); initQtnPropertyWidgetLibrary(); QtnPropertySet* propertySet = new QtnPropertySet(this); // BOOL的两种表现形式 { QtnPropertySet* propertyBOOL = new QtnPropertySet(propertySet); propertyBOOL->setName("BOOL的两种表现形式"); //CheckBox形式 auto boolValue = new QtnPropertyBool(propertyBOOL); boolValue->setName("Bool_CheckBox"); boolValue->setDescription("It is bool value"); boolValue->setValue(true); //ComboBox形式 auto boolValue2 = new QtnPropertyBool(propertyBOOL); boolValue2->setName("Bool_ComboBox"); boolValue2->setDescription("It is bool value"); boolValue2->setValue(false); QtnPropertyDelegateInfo boolNewDelegate; boolNewDelegate.name = "ComboBox"; boolNewDelegate.attributes["labelFalse"] = "否"; boolNewDelegate.attributes["labelTrue"] = "是"; boolValue2->setDelegate(boolNewDelegate); } //INT和FLOAT的表现形式 { QtnPropertySet* propertyINT = new QtnPropertySet(propertySet); propertyINT->setName("INT的三种表现形式"); //SpinBox形式 auto intValue = new QtnPropertyInt(propertyINT); intValue->setName("Int_SpinBox"); intValue->setDescription("This is integer Value 0 ~ 9"); intValue->setMaxValue(9); intValue->setMinValue(0); intValue->setValue(1); //SliderBox形式 auto intValue2 = new QtnPropertyInt(propertyINT); intValue2->setName("Int_SliderBox"); intValue2->setDescription("This is integer Value 0 ~ 9"); intValue2->setMaxValue(9); intValue2->setMinValue(0); intValue2->setValue(2); QtnPropertyDelegateInfo intNewDel1; intNewDel1.name = "SliderBox"; intValue->setDelegate(intNewDel1); //IntList形式 auto intValue3 = new QtnPropertyInt(propertyINT); intValue3->setName("Int_List"); intValue3->setDescription("This is integer Value 0 ~ 9"); intValue3->setMaxValue(9); intValue3->setMinValue(0); intValue3->setValue(2); QList<int> IntList; for (auto i=0; i<10; i++) { IntList.append(i); } QtnPropertyDelegateInfo intNewDel2; intNewDel2.name = "IntList"; intNewDel2.attributes.insert("values", QVariant::fromValue(IntList)); intValue3->setDelegate(intNewDel2); //FLOAT的默认形式 auto floatValue = new QtnPropertyFloat(propertyINT); floatValue->setName("FloatValue"); floatValue->setDescription("Float value"); floatValue->setMaxValue(10.f); floatValue->setMinValue(0.f); floatValue->setStepValue(0.5f); floatValue->setValue(5.0f); } //Enum的表现形式 { QtnPropertySet* propertyENUM = new QtnPropertySet(propertySet); propertyENUM->setName("Enum的表现形式"); auto enumValue = new QtnPropertyEnum(propertyENUM); enumValue->setName("设备串口编号:"); enumValue->setDescription("请选择正确的设备链接端口"); QVector<QtnEnumValueInfo> vec; vec.push_back(QtnEnumValueInfo(0, "NONE", "未选择")); vec.push_back(QtnEnumValueInfo(1, "COM1", "COM1")); vec.push_back(QtnEnumValueInfo(2, "COM2", "COM2")); vec.push_back(QtnEnumValueInfo(3, "COM3", "COM3")); auto enumInfo = new QtnEnumInfo("请选择串口", vec); enumValue->setEnumInfo(enumInfo); } //窗口属性 { QtnPropertySet* propertyWnd = new QtnPropertySet(propertySet); propertyWnd->setName("Windows窗口属性"); //QPoint形式 auto wndPt = new QtnPropertyQPoint(propertyWnd); wndPt->setName("Point"); wndPt->setDescription("This is Windows Point"); wndPt->setValue(QPoint(320, 240)); //QSize形式 auto wndSize = new QtnPropertyQSize(propertyWnd); wndSize->setName("Size"); wndSize->setDescription("This is Windows Size"); wndSize->setValue(QSize(640, 480)); //QRect形式 auto wndRect = new QtnPropertyQRect(propertyWnd); wndRect->setName("Rect"); wndRect->setDescription("This is the windows rectange."); wndRect->setValue(QRect(0, 0, 10, 20)); } //String的三种形式 { QtnPropertySet* propertyStr = new QtnPropertySet(propertySet); propertyStr->setName("String的三种形式"); //LineEdit形式 auto strEdit = new QtnPropertyQString(propertyStr); strEdit->setName("窗口标题"); strEdit->setDescription("请输入窗口的标题"); strEdit->setValue("未命名"); //File形式 auto strFile = new QtnPropertyQString(propertyStr); strFile->setName("选择文件路径"); strFile->setDescription("请选择指定的文件"); QtnPropertyDelegateInfo fileDele; fileDele.name = "File"; fileDele.attributes["acceptMode"] = QFileDialog::AcceptOpen; fileDele.attributes["defaultSuffix"] = "Text File | *.txt"; fileDele.attributes["fileMode"] = QFileDialog::ExistingFile; fileDele.attributes["options"] = QFileDialog::ExistingFile; fileDele.attributes["viewMode"] = QFileDialog::Detail; strFile->setDelegate(fileDele); //List形式 auto strList = new QtnPropertyQString(propertyStr); strList->setName("设备类型"); strList->setDescription("请选择设备的类型"); QtnPropertyDelegateInfo listDele; listDele.name = "List"; listDele.attributes["items"] = QStringList()<<"单机设备"<<"联网设备"<<"其余类型"; strList->setDelegate(listDele); } //杂项 { QtnPropertySet* propertyOther = new QtnPropertySet(propertySet); propertyOther->setName("杂项"); //Button auto button = new QtnPropertyButton(propertyOther); button->setName("HelloButton"); button->setDescription("This is Button"); button->setClickHandler([this](const QtnPropertyButton* btn){ QMessageBox::information(this, "Message", QString("Button Message from %1 : Hello, I am Button Style !").arg(btn->name())); }); //Brush auto brush = new QtnPropertyQBrushStyle(propertyOther); brush->setName("Brush"); brush->setDescription("This is Brush"); brush->setValue(Qt::SolidPattern); //Color auto color = new QtnPropertyQColor(propertyOther); color->setName("Color"); color->setDescription("This is Color"); color->setValue(QColor(255, 0, 0)); //Font auto font = new QtnPropertyQFont(propertyOther); font->setName("Font"); font->setDescription("This is Font"); font->setValue(QFont("宋体", 10)); //PenStyle auto penStyle = new QtnPropertyQPenStyle(propertyOther); penStyle->setName("PenStyle"); penStyle->setDescription("This is Pen"); penStyle->setValue(Qt::SolidLine); //Pen // auto pen = new QtnPropertyQPen(propertyOther); // pen->setName("Pen"); // pen->setValue(QPen(Qt::SolidLine)); } ui->property->setPropertySet(propertySet); } Widget::~Widget() { delete ui; }
最后上个效果截图: