• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            eryar

            PipeCAD - Plant Piping Design Software.
            RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
            posts - 603, comments - 590, trackbacks - 0, articles - 0

            QCAD Plugin 開發(fā)

            Posted on 2018-06-21 23:28 eryar 閱讀(2682) 評論(0)  編輯 收藏 引用 所屬分類: 6.Others

            QCAD Plugin 開發(fā)

            eryar@163.com

            Abstract. QCAD是基于GPL協(xié)議的開源CAD軟件,核心功能基于Qt使用C++開發(fā),界面及其交互使用Javascript腳本進(jìn)行開發(fā)。QCAD官方推薦開發(fā)其Plugin的方式為使用Javascript腳本的方式,因為QCAD的菜單及其對應(yīng)的功能全部由Javascript實(shí)現(xiàn)。程序有時也需要和C++直接通信,如在QCAD中使用OpenCASCADE。本文主要介紹如何來開發(fā)QCAD的插件Plugin,從而能夠?qū)CAD進(jìn)行擴(kuò)展,做一些定制化的功能開發(fā)。

            Key Words. QCAD Plugin, Javascript, C++, CAD, 3D

            1.Introduction

            QCAD是GPL協(xié)議的開源CAD軟件,主要使用Javascript腳本進(jìn)行開發(fā),也可使用C++開發(fā)。與AutoCAD的多種開發(fā)方式一樣,支持AutoLisp腳本,也支持ObjectArx使用C++進(jìn)行開發(fā)。不過開源的程序可以進(jìn)行源碼Debug,遇到問題可以自己動手解決。而AutoCAD是閉源的,如果是正版用戶可以咨詢開發(fā)廠家,不能追根溯源。對于想學(xué)習(xí)CAD的人來說,建議可以多看這種開源軟件,學(xué)習(xí)CAD的開發(fā)原理。

            本文主要介紹開源軟件QCAD的插件Plugin的開發(fā)方法。

            2.Javascript

            由于QCAD的菜單、交互都提供了Javascript的封裝,所以QCAD的大部分功能都是用Javascript腳本實(shí)現(xiàn)。使Javascript腳本對QCAD進(jìn)行開發(fā)也是QCAD作者推薦的方式。

            https://www.qcad.org/doc/qcad/latest/developer/_script_scope.html

            QCAD程序框架提供了一很完整的強(qiáng)大的ECMAScript接口,QCAD幾乎所有的功能都可以通過腳本JavaScript來訪問。ECMAScript(JavaScript)是很流行且易于學(xué)習(xí)的一種腳本語言。通過使用JavaScript腳本來擴(kuò)展QCAD是一種簡單高效的方式,擴(kuò)展的功能包括交互創(chuàng)建、修改工具等等。

            wps_clip_image-21599

            用戶甚至可以基于QCAD的應(yīng)用框架開發(fā)出一個全新的程序。全新的程序可能是一個控制臺工具或包含用戶交互的CAD程序:

            wps_clip_image-12615

            如下圖所示為QCAD中主要模塊的功能。Qt主要涉及通用的功能,與CAD沒有直接關(guān)系。QCAD程序框架QCAD Application Framework提供CAD專用功能,如CAD Core, DXF導(dǎo)入導(dǎo)出、強(qiáng)大的圖形視圖powerful graphics view等等。腳本ECMAScript可以用來快速的擴(kuò)展CAD專用功能。QCAD用戶接口及所有的交互功能、幾乎所有的窗口都是通過腳本實(shí)現(xiàn)的。

            QCAD包中的qcad.exe就是一個ECMAScript解釋器,并且封裝了Qt和QCAD的接口。當(dāng)沒有任何ECMAScript腳本的時候,運(yùn)行qcad.exe將會什么也不做。Qcad.exe默認(rèn)會查找“scripts/autostart.js”并執(zhí)行。在QCAD中,autostart.js腳本初始化了所有的ECMAScript工具和用戶交互的功能,并啟動主程序。

            QCAD中幾乎所有的窗口、菜單、工具欄都是通過ECMAScript腳本實(shí)現(xiàn)。這些腳本位于scripts文件夾中。

            wps_clip_image-10035

            用JavaScript腳本開發(fā)QCAD插件最好辦法就是先在QCAD中創(chuàng)建菜單和工具欄。下面就給出在QCAD中創(chuàng)建菜單和工具欄的步驟。首先要創(chuàng)建文件結(jié)構(gòu):

            l 對于新的頂層菜單,在QCAD目錄中的scripts文件夾中創(chuàng)建一個新的文件夾。例如:創(chuàng)建一個“MyScripts”的文件夾;

            l 在MyScripts文件夾中創(chuàng)建一個文本文件“MyScripts.js”;

            l 在MyScripts文件夾中創(chuàng)建另外一個文件夾來提供一個命令A(yù)ction,如命名為“MyAction”;

            l 在MyAction文件夾中創(chuàng)建一個文本文件MyAction.js,文件名必須和文件夾的名字一致;

            文件組織結(jié)構(gòu)如下所示:

            wps_clip_image-11506

            將如下JavaScript腳本復(fù)制到MyScripts.js文件中:

            /**
             * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
             * 
             * This file is part of the QCAD project.
             *
             * QCAD is free software: you can redistribute it and/or modify
             * it under the terms of the GNU General Public License as published by
             * the Free Software Foundation, either version 3 of the License, or
             * (at your option) any later version.
             *
             * QCAD is distributed in the hope that it will be useful,
             * but WITHOUT ANY WARRANTY; without even the implied warranty of
             * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
             * GNU General Public License for more details.
             *
             * You should have received a copy of the GNU General Public License
             * along with QCAD.
             */
            // MyScripts.js
            // All actions are derived from class EAction, so we need to 
            // include this class definition here:
            include("../EAction.js");
            // Constructor calls base class constructor:
            function MyScripts(guiAction) {
                EAction.call(this, guiAction);
            }
            // Derive class MyScripts from class EAction:
            MyScripts.prototype = new EAction();
            // This static function returns a new or existing QMenu object.
            MyScripts.getMenu = function() {
                // EAction.getMenu is a helper function that returns an existing 
                // or new QMenu object with the given title and object name.
                // The object name (here "MyScriptMenu") must be unique. 
                return EAction.getMenu(MyScripts.getTitle(), "MyScriptsMenu");
            };
            // This static function returns a new or existing QToolBar object.
            MyScripts.getToolBar = function() {
                // EAction.getToolBar is a helper function that returns an existing 
                // or new QToolBar object with the given title and object name.
                // The object name (here "MyScriptToolBar") must be unique. 
                return EAction.getToolBar(MyScripts.getTitle(), "MyScriptToolBar");
            };
            // This static function defines and returns the title of the menu 
            // and toolbar.
            // The qsTr function marks the title as a translatable string.
            MyScripts.getTitle = function() {
                return qsTr("My Scripts");
            };
            // Init creates the menu and toolbar on start.
            MyScripts.init = function() {
                MyScripts.getMenu();
                MyScripts.getToolBar();
            };

             

            將如下腳本代碼復(fù)制到MyAction.js文件中:

            /**
             * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
             * 
             * This file is part of the QCAD project.
             *
             * QCAD is free software: you can redistribute it and/or modify
             * it under the terms of the GNU General Public License as published by
             * the Free Software Foundation, either version 3 of the License, or
             * (at your option) any later version.
             *
             * QCAD is distributed in the hope that it will be useful,
             * but WITHOUT ANY WARRANTY; without even the implied warranty of
             * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
             * GNU General Public License for more details.
             *
             * You should have received a copy of the GNU General Public License
             * along with QCAD.
             */
            // MyAction.js
            // Include base class definition:
            include("../MyScripts.js");
            // Constructor calls base class constructor:
            function MyAction(guiAction) {
                MyScripts.call(this, guiAction);
            }
            // Derive class MyAction from class MyScripts:
            MyAction.prototype = new MyScripts();
            // This function is called immediately after the constructor when the user 
            // starts this action. For actions that don't require any user input (for
            // example auto zoom), beginEvent does everything and then terminates the
            // action.
            MyAction.prototype.beginEvent = function() {
                // call base class implementation of beginEvent:
                MyScripts.prototype.beginEvent.call(this);
                // get main application window:
                var appWin = EAction.getMainWindow();
                // print a message in the console of QCAD:
                appWin.handleUserMessage("MyAction() is running...");
                // terminate this action immediately:
                this.terminate();
            };
            // MyAction.init() is called by QCAD to initialize the action and create
            // the menu / toolbar for it.
            MyAction.init = function(basePath) {
                // Create a new RGuiAction (extended QAction):
                var action = new RGuiAction("&My Action", RMainWindowQt.getMainWindow());
                // This action requires a document to be open. If no document is
                // open, the menu and tool button are grayed out:
                action.setRequiresDocument(true);
                // Define the script file that is executed when this action is
                // launched:
                action.setScriptFile(basePath + "/MyAction.js");
                // Set the icon that is shown in the toolbar and on some platforms
                // also in the menu:
                action.setIcon(basePath + "/MyAction.svg");
                // Set the command(s) that can be used on the command line to 
                // launch this action:
                action.setDefaultCommands(["myaction"]);
                // Define the sort order of this action. Menus and tool buttons are
                // ordered by these values:
                action.setGroupSortOrder(80100);
                action.setSortOrder(200);
                // Set list of widgets this action is added to
                // (menus, tool bars, CAD tool bar panels):
                action.setWidgetNames(["MyScriptsMenu"]);
            };

             

            啟動QCAD可以發(fā)現(xiàn)在菜單上有了MyScripts,如下圖所示:

            wps_clip_image-31967

            點(diǎn)擊MyAction菜單,會在命令窗口中輸出測試文字。

            3.C++

            既然QCAD的是基于Qt開發(fā)的,理所當(dāng)然地應(yīng)該支持C++開發(fā),只是C++開發(fā)方式需要與JavaScript相結(jié)合。因為QCAD中一些交互功能封裝到JavaScript腳本中了,所以只能通過在JavaScript中調(diào)用C++。這種方式QCAD也提供了一個例子,位于源碼的

            support\examples\exampleplugin中。主要是將C++的類暴露給JavaScript,使在JavaScript中可以調(diào)用C++的類及其方法。只將頭文件源碼列出如下:RExamplePlugin.h

            #include <QDebug>
            #include <QObject>
            #include <QScriptEngine>
            #include <QStringList>
            #include "RActionAdapter.h"
            #include "RDocumentInterface.h"
            #include "RGuiAction.h"
            #include "RMainWindow.h"
            #include "RPluginInterface.h"
            class MyAction : public RActionAdapter {
            public:
                MyAction(RGuiAction* guiAction) : RActionAdapter(guiAction) {}
                static void factory(RGuiAction* guiAction) {
                    qDebug() << "MyAction::factory";
                    if (guiAction==NULL) {
                        qDebug("guiAction is NULL");
                        return;
                    }
                    RDocumentInterface* di = RMainWindow::getDocumentInterfaceStatic();
                    if (di==NULL) {
                        qDebug("di is NULL");
                        return;
                    }
                    di->setCurrentAction(new MyAction(guiAction));
                }
                virtual void beginEvent() {
                    qDebug() << "MyAction::beginEvent";
                }
            };
            class MyClass : public QObject {
            Q_OBJECT
            public:
                MyClass() : QObject(), i(0), d(0.0) {}
                virtual int getInt() const {
                    return i;
                }
                virtual double getDouble() const {
                    return d;
                }
                virtual QString getString() const {
                    return s;
                }
                virtual void setInt(int v) {
                    i = v;
                }
                virtual void setDouble(int v) {
                    d = v;
                }
                virtual void setString(const QString& v) {
                    s = v;
                }
                void emitSignal() {
                    emit mySignal(i);
                }
            signals:
                void mySignal(int code);
            private:
                int i;
                double d;
                QString s;
            };
            Q_DECLARE_METATYPE(MyClass*)
            /**
             * Script binding for MyClass.
             */
            class EcmaMyClass {
            public:
                static void initEcma(QScriptEngine& engine);
                static QScriptValue createMyClass(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue myClassToString(QScriptContext *context, QScriptEngine *engine);
                static MyClass* getSelfMyClass(const QString& fName, QScriptContext* context);
                static QScriptValue getInt(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue getDouble(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue getString(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue setInt(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue setDouble(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue setString(QScriptContext* context, QScriptEngine* engine);
                static QScriptValue emitSignal(QScriptContext* context, QScriptEngine* engine);
            };
            class RExamplePlugin : public QObject, public RPluginInterface
            {
                Q_OBJECT
                Q_INTERFACES(RPluginInterface)
            #if QT_VERSION >= 0x050000
                Q_PLUGIN_METADATA(IID "org.qcad.exampleplugin")
            #endif
            public:
                virtual bool init();
                virtual void uninit(bool) {}
                virtual void postInit(InitStatus status);
                virtual void initScriptExtensions(QScriptEngine& engine);
                virtual RPluginInfo getPluginInfo();
            };

             

            從上述源碼可以看出,通過Qt的Plguin機(jī)制將C++的類暴露給JavaScript,從而在JavaScript中使用C++的功能。如下圖所示為在QCAD中通過JavaScript調(diào)用C++來顯示一個三維視圖的窗口。

            wps_clip_image-25228

            4.Conclusion

            綜上所述,QCAD二次開發(fā)的方式主要是以JavaScript為主。如果要在QCAD中使用C++,或者是使用C++的第三方庫,只能是將相關(guān)的C++類暴露給JavaScirpt,這樣開發(fā)才是最簡單的。如果純用C++開發(fā),一些交互功能是封裝在JavaScript中,反而效率不高。

            通過在QCAD中使用OpenCASCADE之類的三維幾何內(nèi)核,可以實(shí)現(xiàn)一些建模、出圖的功能。

            5.References

            1. https://www.qcad.org/doc/qcad/latest/developer/_menus_and_tool_bars.html

            2. https://www.qcad.org/doc/qcad/latest/developer/index.html#what_is

            3. https://www.qcad.org/rsforum/viewforum.php?f=30&sid=8621b8249232845e54252ef7fa6b34ae

            4. JavaScript 高級程序設(shè)計

            5. C++ GUI Programming with Qt


            為了方便大家在移動端也能看到我的博文和討論交流,現(xiàn)已注冊微信公眾號,歡迎大家掃描下方二維碼關(guān)注。
            Shing Liu(eryar@163.com)

             

            99久久超碰中文字幕伊人| 99国产精品久久久久久久成人热| 久久免费精品一区二区| 国产精品久久99| 久久精品这里只有精99品| 欧美久久久久久| 久久久久久久人妻无码中文字幕爆| 69SEX久久精品国产麻豆| 久久99精品免费一区二区| 久久亚洲国产精品成人AV秋霞| 精品熟女少妇av免费久久| 久久久久香蕉视频| 成人免费网站久久久| 色综合久久天天综线观看| 久久福利青草精品资源站免费| 色婷婷狠狠久久综合五月| 久久久久久综合一区中文字幕| 亚洲国产成人久久一区WWW| 久久伊人精品青青草原高清| 欧美一区二区久久精品| 久久久精品久久久久久| 国产精品久久久久久搜索| 国内精品伊人久久久影院| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 嫩草伊人久久精品少妇AV| 久久精品无码专区免费| 国产亚洲美女精品久久久久狼| 国产激情久久久久久熟女老人| 日本精品久久久久影院日本 | 精品九九久久国内精品| 亚洲熟妇无码另类久久久| 日韩精品无码久久一区二区三| 久久电影网2021| 国产成人久久777777| 91超碰碰碰碰久久久久久综合| 国产成人精品白浆久久69| 久久ZYZ资源站无码中文动漫| 久久亚洲春色中文字幕久久久| 亚洲人成网亚洲欧洲无码久久| 18禁黄久久久AAA片| A级毛片无码久久精品免费|