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; }
最後上個效果截圖: