美文网首页
qt 解析xml生成界面,按钮响应command注册

qt 解析xml生成界面,按钮响应command注册

作者: 诸事圆成 | 来源:发表于2021-01-22 17:04 被阅读0次

    传统操作都是通过qtCreator 手动画界面,托按钮建立处理槽函数
    这样做有以下不好:

    • 改界面比较麻烦
    • 如果把一个widget的按钮,移动到另一个widget,而且这2个widget是不同人写的,移动按钮位置会特别麻烦,因为按钮响应的处理函数里,可能用到一些类的成员变量。。。
    效果
    image.png image.png

    分享一下我的代码,我的项目暂时只用到QToolButton,所以下面写的比较简单

    1. 创建xml,解析xml接口


    XmlRecipe.h

    #ifndef  XMLRECIPE_H
    #define XMLRECIPE_H
    
    #include <QXmlStreamWriter>
    #include <QXmlStreamReader>
    #include <QMap>
    #include <QVector>
    #include <QDebug>
    
    typedef struct 
    {
        QString _Type;  /* 按钮类型 */
        QString _Text;   /* 按钮显示文字 */
        QString _Size;   /* 按钮大小 */
        QString _Cmd;  /* 点击按钮发送的command*/
        QString _Group; /* 按钮属于哪个组 */
    }UI_Config;
    
    class XmlRecipe
    {
    public:
        XmlRecipe();
    public:
        /** 写xml, 一个ui对应一个xml */
        /* 文件 */
        static bool xmlWrite_fileOperation(QString path);   
    public:
        /** 读xml,一个ui对应一个xml*/
        static bool xmlReader(QString path, QString &widgetTitle, QMap<int, QVector<UI_Config>> &retMap);
        //每个按钮的节点遍历
        static void ParseButton(QXmlStreamReader &reader, UI_Config &obj);
    };
    
    #endif // XMLRECIPE_H
    
    

    XmlRecipe.cpp

    #include "XmlRecipe.h"
    #include <QFile>
    
    XmlRecipe::XmlRecipe()
    {
    
    }
    
    /***********************************************************************************
        生成一个界面的xml
    ***********************************************************************************/
    bool XmlRecipe::xmlWrite_fileOperation(QString path)
    {
        QFile f(path);
        if(!f.open(QIODevice::WriteOnly | QIODevice::Text))
            return false;
    
        QXmlStreamWriter writer(&f);
        writer.setAutoFormatting(true);
        writer.writeStartDocument();
        writer.writeStartElement("JQRecipe");
        writer.writeAttribute("Title", "文件" );
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "打开" );
        writer.writeTextElement("Command", "OPEN_FILE");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "文件编辑_1"); //这个加个后缀1是为了后面排序
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "新建" );
        writer.writeTextElement("Command", "NEW_FILE");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "文件编辑_1");
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "保存" );
        writer.writeTextElement("Command", "SAVE_FILE");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "文件编辑_1");
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "另存" );
        writer.writeTextElement("Command", "SAVEAS_FILE");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "文件编辑_1");
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "撤销" );
        writer.writeTextElement("Command", "BACKWARD");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "操作_2");
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "恢复" );
        writer.writeTextElement("Command", "ForWARD");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "操作_2");
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "导入CAD" );
        writer.writeTextElement("Command", "IMPORT_CAD");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "导入_3");
        writer.writeEndElement();
    
        writer.writeStartElement("Button");
        writer.writeTextElement("Type", "QToolButton");
        writer.writeTextElement("Text", "缩放" );
        writer.writeTextElement("Command", "CAD_ZOOM");
        writer.writeTextElement("Size", "60,60");
        writer.writeTextElement("Group", "导入_3");
        writer.writeEndElement();
    
        writer.writeEndElement();
        writer.writeEndDocument();
    
        f.close();
    
        return true;
    }
    
    
    
    /***********************************************************************************
        解析一个界面的xml
    ***********************************************************************************/
    bool  XmlRecipe::xmlReader(QString path, QString &widgetTitle, QMap<int, QVector<JQ_UI_Config>> &retMap)
    {
        retMap.clear();
    
        QFile f(path);
        if(!f.open(QIODevice::ReadOnly | QIODevice::Text))
            return false;
    
        QXmlStreamReader reader(&f);
        while(!reader.atEnd())
        {
            QXmlStreamReader::TokenType type=reader.readNext();
    
            if (type == QXmlStreamReader::StartElement && reader.name() == "JQRecipe")
            {
                QXmlStreamAttributes attributes = reader.attributes();
                if (attributes.hasAttribute("Title")) {
                    widgetTitle = attributes.value("Title").toString();
                }
            }
    
            if(type == QXmlStreamReader::StartElement &&  reader.name() == "Button")
            {
                UI_Config obj;
                ParseButton(reader, obj);
                int key = obj._Group.split('_').at(1).toInt();
                if (retMap.find(key) == retMap.end())
                {
                    QVector<UI_Config> vec;
                    vec.push_back(obj);
                    retMap.insert(key, vec);
                }
                else
                {
                    retMap.find(key).value().push_back(obj);
                }
            }
        }
    
        reader.clear();
        f.close();
    
        return true;
    }
    
    /***********************************************************************************
        解析QToolButton节点数据
    ***********************************************************************************/
    void XmlRecipe::ParseButton(QXmlStreamReader &reader, UI_Config &obj)
    {
        while (!reader.hasError())
        {
            if (reader.isEndElement() && reader.name() == "Button")
                break;
    
            if (reader.isStartElement() && reader.name() == "Type")
            {
                obj._Type = reader.readElementText();
            }
            else if (reader.isStartElement() && reader.name() == "Text")
            {
                obj._Text = reader.readElementText();
            }
            else if (reader.isStartElement() && reader.name() == "Command")
            {
                obj._Cmd = reader.readElementText();
            }
            else if (reader.isStartElement() && reader.name() == "Size")
            {
                obj._Size = reader.readElementText();
            }
            else if (reader.isStartElement() && reader.name() == "Group")
            {
                obj._Group = reader.readElementText();
            }
    
            reader.readNext();
        }
    }
    

    2. 解析上面读取xml获取的数据,生成QWidget


    JQWidgetgenerate .h

    #ifndef JQWIDGETGENERATE_H
    #define JQWIDGETGENERATE_H
    
    #include "core/doc/JQXmlRecipe.h"
    #include <QWidget>
    
    
    /**
     * @brief The JQWidgetgenerate class
     * #构建xml数据获取的Widget
     */
    class JQWidgetgenerate : public QWidget
    {
        Q_OBJECT
    public:
        JQWidgetgenerate(QWidget *parent = nullptr);
    
        void   setupJQUi(QMap<int, QVector<JQ_UI_Config>> &map, QString windowTitle);
    
    signals:
        void sendCMD(QString);
    
    };
    
    #endif // JQWIDGETGENERATE_H
    
    

    JQWidgetgenerate .cpp

    #include "JQWidgetgenerate.h"
    
    #include <QGridLayout>
    #include <QToolButton>
    #include <QLabel>
    #include <QFrame>
    #include <QCoreApplication>
    
    JQWidgetgenerate::JQWidgetgenerate(QWidget *parent) : QWidget(parent)
    {
    }
    
    void JQWidgetgenerate::setupJQUi(QMap<int, QVector<JQ_UI_Config>> &map, QString windowTitle)
    {
    //图片路径
    #ifdef Q_OS_MAC
        QString currentExeDir = QCoreApplication::applicationDirPath() +"/../Resources/Images/";
    #else
        QString currentExeDir = QCoreApplication::applicationDirPath() +"/Resources/Images/";
    #endif
    
        QString style =
                "QToolButton{ border-style:flat;}"
                "QToolButton:hover{color:rgb(75,0,130); min-height:40; border-style:solid; "
                " border-top-left-radius:2px;"
                " border-top-right-radius:2px;"
                " border:1px;"
                " border-radius:5px;padding:2px 4px;"
                ;
    
        QWidget *retWidget = this;
        retWidget->setObjectName(windowTitle);
        retWidget->resize(700, 110);
        QGridLayout *gridLayout = new QGridLayout(retWidget);
        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
        gridLayout->setSizeConstraint(QLayout::SetFixedSize);
        gridLayout->setHorizontalSpacing(0);
        gridLayout->setVerticalSpacing(10);
        //左上右后
        gridLayout->setContentsMargins(0, -1, 0, 0);
    
        int index_btn = 0;
        int index_label = 0;
        for (auto iter = map.begin(); iter != map.end(); iter++)
        {
            QVector<JQ_UI_Config> &vec = iter.value();
            int count = 0;
            for (const auto &it : vec)
            {
                if (it._Type == "QToolButton")
                {
                    QToolButton *toolBtn = new QToolButton();
                    toolBtn->setText(it._Text);
                    QSize btnSize(it._Size.split(',').at(0).toInt(), it._Size.split(',').at(1).toInt());
                    toolBtn->setFixedSize(btnSize);
                    toolBtn->setAutoRaise(false);
                    toolBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
                    QString picture = QString("%1%2.svg").arg(currentExeDir).arg(it._Text);
                    toolBtn-> setIcon(QIcon(QPixmap(picture)));
                    int width = toolBtn->width();
                    int height = toolBtn->height();
                    toolBtn->setIconSize(QSize(width,  height-25));
                    QString cmd = it._Cmd;
                    toolBtn->setStyleSheet(style);
                    connect(toolBtn, &QToolButton::clicked, this, [this,  cmd](){
                        qDebug() << "__SCMD:  " << cmd;
                        emit  sendCMD(cmd);
                    });
                    gridLayout->addWidget(toolBtn, 0, index_btn++, 1, 1);
                    count++;
                }
                else
                {
                    //undefine
                }
            }
            QLabel *label = new QLabel(retWidget);
            label->setAlignment(Qt::AlignCenter);
            QFont font;
            font.setBold(true);
            font.setWeight(50);
            label->setFont(font);
            label->setText(vec[0]._Group.split("_").at(0));
            label->setFixedHeight(20);
            label->setBackgroundRole(QPalette::ColorRole::HighlightedText);
            label->setStyleSheet("QLabel{background-color: rgb(222,236,252);}");
            gridLayout->addWidget(label, 1, index_label, 1, count);
    
            QFrame *line = new QFrame(retWidget);
            line->setFrameShadow(QFrame::Raised);
            line->setFrameShape(QFrame::VLine);
            gridLayout->addWidget(line, 0, index_label, 2, 1);
            index_label = index_btn;
        }
        retWidget->setLayout(gridLayout);
    }
    
    

    3. 注册command,一个command过来自动回调处理函数

    #ifndef COMMANDHANDLER_H
    #define COMMANDHANDLER_H
    
    //类成员函数指针
    typedef void (commandHandler::*pFunc)();
    
    class commandHandler
    {
    public:
        commandHandler()
        {
            m_registerMap.clear();
        }
    
        void registerCommand()
        {//注册, command和xml中按钮的cmd对应
            m_registerMap.insert("OPEN_FILE",  &commandHandler::handle_openFile);
            m_registerMap.insert("SAVE_FILE",  &commandHandler::handle_saveFile);
            m_registerMap.insert("SAVEAS_FILE",  &commandHandler::handle_saveAsFile);
    
        }
    
        void parseCommand(const QString &cmd)
        {
            if (m_registerMap.isEmpty())
                return;
    
            if (m_registerMap.find(cmd) != m_registerMap.end())
            {
                auto pFunc = m_registerMap.find(cmd).value();
                (this->*pFunc)();
            }
        }
    
    public:
        /* 处理函数 */
        //打开
        void handle_openFile();
        //保存
        void handle_saveFile();
        //另存
        void handle_saveAsFile();
        //....
    private:
        QMap<QString, pFunc> m_registerMap;
    
    };
    
    #endif // COMMANDHANDLER_H
    
    

    相关文章

      网友评论

          本文标题:qt 解析xml生成界面,按钮响应command注册

          本文链接:https://www.haomeiwen.com/subject/qwxezktx.html