亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Qt如何實現用戶屬性

發布時間:2021-12-15 10:21:40 來源:億速云 閱讀:191 作者:小新 欄目:互聯網科技

這篇文章將為大家詳細講解有關Qt如何實現用戶屬性,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

一、前言

用戶屬性是后面新增加的一個功能,自定義控件如果采用的Q_PROPERTY修飾的屬性,會自動識別到屬性欄中,這個一般稱為控件屬性,在組態設計軟件中,光有控件本身的控件屬性還是不夠的,畢竟這些屬性僅僅是以外觀為主,并不能表示某個設備的屬性,所以需要除了這個控件屬性以外增加用戶屬性來存儲該控件關聯的設備屬性,比如設備編號、設備名稱、地理位置等信息,而這些信息也要和控件屬性一樣,都能導入導出到xml文件,同時能支持多個用戶屬性,用戶自己填寫名字和值,名字和值都支持中文描述,在xml文件中為了區分用戶屬性和控件屬性,特意在用戶屬性前面加上user-前綴來表示,這樣在讀取xml文件加載控件的時候,識別到user-開頭的都存儲到該控件的用戶屬性列表中。自從有了用戶屬性的機制,大大拓展了控件的現有功能,相當于可以綁定N個自定義的數據,而這些用戶屬性直接采用setProperty來設置即可,然后通過property來讀取就行,為了支持中文的屬性名稱,需要設置屬性的時候轉換一下:widget->setProperty(name.toStdString().c_str(), value);

二、實現的功能

  1. 自動加載插件文件中的所有控件生成列表,默認自帶的控件超過120個。

  2. 拖曳到畫布自動生成對應的控件,所見即所得。

  3. 右側中文屬性欄,改變對應的屬性立即應用到對應選中控件,直觀簡潔,非常適合小白使用。

  4. 獨創屬性欄文字翻譯映射機制,效率極高,可以非常方便拓展其他語言的屬性欄。

  5. 所有控件的屬性自動提取并顯示在右側屬性欄,包括枚舉值下拉框等。

  6. 支持手動選擇插件文件,外部導入插件文件。

  7. 可以將當前畫布的所有控件配置信息導出到xml文件。

  8. 可以手動選擇xml文件打開控件布局,自動根據xml文件加載控件。

  9. 可拉動滑動條、勾選模擬數據復選框、文本框輸入,三種方式來生成數據應用所有控件。

  10. 控件支持八個方位拉動調整大小,自適應任意分辨率,可鍵盤上下左右微調位置。

  11. 打通了串口采集、網絡采集、數據庫采集三種方式設置數據。

  12. 代碼極其精簡,注釋非常詳細,可以作為組態的雛形,自行拓展更多的功能。

  13. 純Qt編寫,支持任意Qt版本+任意編譯器+任意系統。

三、效果圖

Qt如何實現用戶屬性

四、核心代碼

void frmMain::openFile(const QString &fileName)
{
    //如果控件列表沒有則不用繼續
    if (ui->listWidget->count() == 0) {
        return;
    }

    //打開文件
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        return;
    }

    //將文件填充到dom容器
    QDomDocument doc;
    if (!doc.setContent(&file)) {
        file.close();
        return;
    }

    file.close();

    listSelect.clear();
    listUserProperty.clear();
    xmlName = fileName;

    //先清空原有控件
    QList<QWidget *> widgets = ui->centralwidget->findChildren<QWidget *>();
    qDeleteAll(widgets);
    widgets.clear();

    //先判斷根元素是否正確
    QDomElement docElem = doc.documentElement();
    if (docElem.tagName() == "canvas") {
        QDomNode node = docElem.firstChild();
        QDomElement element = node.toElement();
        while(!node.isNull()) {
            //控件名稱
            QString name = element.tagName();
            //取出當前控件在控件列表中的索引,如果不存在則意味著配置文件中的該控件不存在了
            int index = listNames.indexOf(name);
            if (index < 0) {
                continue;
            }

            //存儲控件的坐標位置和寬度高度
            int x, y, width, height;
            //存儲自定義控件屬性
            QList<QPair<QString, QVariant> > propertys;
            //存儲控件自定義屬性
            QStringList userProperty;

            //節點名稱不為空才繼續
            if (!name.isEmpty()) {
                //遍歷節點的屬性名稱和屬性值
                QDomNamedNodeMap attrs = element.attributes();
                for (int i = 0; i < attrs.count(); i++) {
                    QDomNode node = attrs.item(i);
                    QString nodeName = node.nodeName();
                    QString nodeValue = node.nodeValue();
                    //qDebug() << name << nodeName << nodeValue;

                    //優先取出坐標+寬高屬性,這幾個屬性不能通過設置弱屬性實現
                    if (nodeName == "x") {
                        x = nodeValue.toInt();
                    } else if (nodeName == "y") {
                        y = nodeValue.toInt();
                    } else if (nodeName == "width") {
                        width = nodeValue.toInt();
                    } else if (nodeName == "height") {
                        height = nodeValue.toInt();
                    } else if (nodeName.startsWith("user-")) {
                        //取出user-開頭的自定義屬性
                        nodeName = nodeName.split("-").last();
                        userProperty << QString("%1|%2").arg(nodeName).arg(nodeValue);
                    } else {
                        QVariant value = QVariant(nodeValue);
                        //為了兼容Qt4,需要將顏色值的rgba分別取出來,因為Qt4不支持16進制字符串帶透明度
                        //#6422a3a9 這種格式依次為 argb 帶了透明度的才需要特殊處理
                        if (nodeValue.startsWith("#") && nodeValue.length() == 9) {
                            bool ok;
                            int alpha = nodeValue.mid(1, 2).toInt(&ok, 16);
                            int red = nodeValue.mid(3, 2).toInt(&ok, 16);
                            int green = nodeValue.mid(5, 2).toInt(&ok, 16);
                            int blue = nodeValue.mid(7, 2).toInt(&ok, 16);
                            value = QColor(red, green, blue, alpha);
                        }

                        propertys.append(qMakePair(nodeName, value));
                    }
                }
            }

            //qDebug() << name << x << y << width << height;

            //根據不同的控件類型實例化控件
            int countWidget = listWidgets.count();
            int countProperty = propertys.count();
            for (int i = 0; i < countWidget; i++) {
                QString className = listWidgets.at(i)->name();
                if (name == className) {
                    //生成對應的控件
                    QWidget *widget = createWidget(i);
                    //逐個設置自定義控件的屬性
                    for (int j = 0; j < countProperty; j++) {
                        QPair<QString, QVariant> property = propertys.at(j);
                        QString name = property.first;
                        QVariant value = property.second;
                        widget->setProperty(name.toStdString().c_str(), value);
                    }

                    //設置控件坐標及寬高
                    widget->setGeometry(x, y, width, height);
                    //實例化選中窗體跟隨控件一起
                    newSelect(widget, userProperty);
                    break;
                }
            }

            //移動到下一個節點
            node = node.nextSibling();
            element = node.toElement();
        }
    }
}

void frmMain::saveFile(const QString &fileName)
{
    //如果控件列表沒有則不用繼續
    if (ui->listWidget->count() == 0) {
        return;
    }

    QFile file(fileName);
    if (!file.open(QFile::WriteOnly | QFile::Text | QFile::Truncate)) {
        return;
    }

    //以流的形式輸出文件
    QTextStream stream(&file);

    //構建xml數據
    QStringList list;

    //添加固定頭部數據
    list << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
    //添加canvas主標簽,保存寬高和背景圖片,還可以自行添加其他屬性
    list << QString("<canvas width=\"%1\" height=\"%2\" image=\"%3\">")
         .arg(ui->centralwidget->width()).arg(ui->centralwidget->height()).arg("bg.jpg");

    //從容器中找到所有控件,根據控件的類名保存該類的所有屬性
    QList<QWidget *> widgets = ui->centralwidget->findChildren<QWidget *>();
    foreach (QWidget *widget, widgets) {
        const QMetaObject *metaObject = widget->metaObject();
        QString className = metaObject->className();

        //如果當前控件的父類不是主窗體則無需導出,有些控件有子控件無需導出
        if (widget->parent() != ui->centralwidget || className == "SelectWidget") {
            continue;
        }

        //逐個存儲自定義控件屬性
        //metaObject->propertyOffset()表示當前控件的屬性開始索引,0開始的是父類的屬性
        QStringList values;
        int index = metaObject->propertyOffset();
        int count = metaObject->propertyCount();
        for (int i = index; i < count; i++) {
            QMetaProperty property = metaObject->property(i);
            QString nodeName = property.name();
            QVariant variant = property.read(widget);
            QString typeName = variant.typeName();
            QString nodeValue = variant.toString();

            //如果是顏色值則取出透明度一起,顏色值toString在Qt4中默認不轉透明度
            if (typeName == "QColor") {
                QColor color = variant.value<QColor>();
                if (color.alpha() < 255) {
                    //Qt4不支持HexArgb格式的字符串,需要挨個取出來拼接
                    //nodeValue = color.name(QColor::HexArgb);
                    QString alpha = QString("%1").arg(color.alpha(), 2, 16, QChar('0'));
                    QString red = QString("%1").arg(color.red(), 2, 16, QChar('0'));
                    QString green = QString("%1").arg(color.green(), 2, 16, QChar('0'));
                    QString blue = QString("%1").arg(color.blue(), 2, 16, QChar('0'));
                    nodeValue = QString("#%1%2%3%4").arg(alpha).arg(red).arg(green).arg(blue);
                }
            }

            //枚舉值要特殊處理,需要以字符串形式寫入,不然存儲到配置文件數據為int
            if (property.isEnumType()) {
                QMetaEnum enumValue = property.enumerator();
                nodeValue = enumValue.valueToKey(nodeValue.toInt());
            }

            values << QString("%1=\"%2\"").arg(nodeName).arg(nodeValue);
            //qDebug() << nodeName << nodeValue << variant;
        }

        //找到當前控件對應的索引
        index = -1;
        count = listSelect.count();
        for (int i = 0; i < count; i++) {
            if (listSelect.at(i)->getWidget() == widget) {
                index = i;
                break;
            }
        }

        //可以用下面方法列出所有的用戶屬性,然后取值,本程序已經用 listUserProperty 存儲了
        //qDebug() << widget->dynamicPropertyNames();

        //逐個存儲控件的用戶屬性
        QStringList userProperty = listUserProperty.at(index);
        count = userProperty.count();
        for (int i = 0; i < count; i++) {
            QStringList list = userProperty.at(i).split("|");
            values << QString("user-%1=\"%2\"").arg(list.at(0)).arg(list.at(1));
        }

        //逐個添加界面上的控件的屬性
        QString geometry = QString("x=\"%1\" y=\"%2\" width=\"%3\" height=\"%4\"").arg(widget->x()).arg(widget->y()).arg(widget->width()).arg(widget->height());
        QString str = QString("\t<%1 %2 %3/>").arg(className).arg(geometry).arg(values.join(" "));
        list << str;
    }

    //添加固定尾部數據
    list << "</canvas>";

    //寫入文件
    QString data = list.join("\n");
    stream << data;
    file.close();
}

關于“Qt如何實現用戶屬性”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

qt
AI

弋阳县| 佛冈县| 山丹县| 隆昌县| 依安县| 普兰店市| 辽中县| 沙湾县| 蓬莱市| 穆棱市| 南木林县| 罗平县| 寿光市| 克什克腾旗| 友谊县| 文水县| 高唐县| 达孜县| 武山县| 固镇县| 中方县| 资兴市| 思茅市| 康定县| 同仁县| 凤翔县| 嘉禾县| 那坡县| 开封市| 登封市| 陵水| 涪陵区| 普兰店市| 杂多县| 胶南市| 黎城县| 白朗县| 江陵县| 同仁县| 成安县| 南漳县|