青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

eryar

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

QCAD Plugin 開發

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

QCAD Plugin 開發

eryar@163.com

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

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

1.Introduction

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

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

2.Javascript

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

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

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

wps_clip_image-21599

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

wps_clip_image-12615

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

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

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

wps_clip_image-10035

用JavaScript腳本開發QCAD插件最好辦法就是先在QCAD中創建菜單和工具欄。下面就給出在QCAD中創建菜單和工具欄的步驟。首先要創建文件結構:

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

l 在MyScripts文件夾中創建一個文本文件“MyScripts.js”;

l 在MyScripts文件夾中創建另外一個文件夾來提供一個命令Action,如命名為“MyAction”;

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

文件組織結構如下所示:

wps_clip_image-11506

將如下JavaScript腳本復制到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();
};

 

將如下腳本代碼復制到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可以發現在菜單上有了MyScripts,如下圖所示:

wps_clip_image-31967

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

3.C++

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

support\examples\exampleplugin中。主要是將C++的類暴露給JavaScript,使在JavaScript中可以調用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機制將C++的類暴露給JavaScript,從而在JavaScript中使用C++的功能。如下圖所示為在QCAD中通過JavaScript調用C++來顯示一個三維視圖的窗口。

wps_clip_image-25228

4.Conclusion

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

通過在QCAD中使用OpenCASCADE之類的三維幾何內核,可以實現一些建模、出圖的功能。

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 高級程序設計

5. C++ GUI Programming with Qt


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

 

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            91久久黄色| 午夜在线观看免费一区| 欧美精品色综合| 亚洲精品女av网站| 韩国亚洲精品| 欧美精品在线观看| 欧美日韩国产不卡在线看| 欧美精品一区在线发布| 欧美精品一区二区三区蜜臀| 欧美—级a级欧美特级ar全黄| 欧美精品日韩www.p站| 欧美日韩免费在线观看| 国产精品女主播一区二区三区| 国产精品五月天| 国内精品视频在线播放| 亚洲日本视频| 午夜精品久久久久久99热| 欧美一区=区| 麻豆精品精品国产自在97香蕉| 欧美成人资源| 一本色道婷婷久久欧美| 欧美一区日韩一区| 欧美国产第二页| 国产精品亚洲综合一区在线观看 | 国内成+人亚洲| 亚洲电影毛片| 亚洲综合电影| 免费在线观看精品| 亚洲午夜极品| 欧美激情在线狂野欧美精品| 国产日本欧美一区二区三区| 136国产福利精品导航| 亚洲手机视频| 亚洲高清123| 午夜精品久久久久| 久久国产精品色婷婷| 欧美日韩国产a| 中文在线资源观看网站视频免费不卡| 久久国产精彩视频| 久久xxxx精品视频| 男女精品视频| 亚洲一区二区高清| 欧美激情综合五月色丁香| 国产欧美一区二区精品忘忧草 | 黄色成人在线网站| 亚洲小说春色综合另类电影| 狼人社综合社区| 中文有码久久| 欧美精品乱人伦久久久久久| 一区久久精品| 久久久久综合一区二区三区| 在线一区亚洲| 欧美色图首页| 亚洲私人影院在线观看| 亚洲欧洲日本国产| 欧美jizzhd精品欧美巨大免费| 国产欧美一区二区精品性 | 国产精品夜夜嗨| 亚洲性夜色噜噜噜7777| 亚洲精品乱码久久久久久黑人 | 国产一区二区剧情av在线| 亚洲影院色无极综合| 亚洲国产日韩欧美一区二区三区| 久久www成人_看片免费不卡| 国产欧美大片| 性欧美暴力猛交69hd| 亚洲视频一起| 国产精品久久午夜| 午夜精品久久久久99热蜜桃导演| 妖精视频成人观看www| 欧美日韩国产综合网| 一本色道久久加勒比精品| 亚洲精品极品| 欧美日韩一区二区三区在线看 | 国产午夜亚洲精品羞羞网站 | 亚洲精品影视在线观看| 欧美精品成人91久久久久久久| 亚洲国产日本| 亚洲人成人一区二区在线观看| 欧美国产日产韩国视频| 亚洲麻豆视频| 国产精品99久久久久久久久 | 亚洲天堂偷拍| 亚洲天堂免费观看| 小辣椒精品导航| 亚洲一区亚洲二区| 国产综合视频| 亚洲国产小视频在线观看| 欧美高清视频| 亚洲欧美在线磁力| 久久精品一区蜜桃臀影院 | 美女精品一区| 欧美激情亚洲激情| 性久久久久久| 美女精品国产| 午夜免费日韩视频| 久久综合五月| 亚洲永久精品国产| 久久久久久久91| 一区二区三区欧美视频| 欧美一区二区三区在线看 | 国产欧美一区在线| 麻豆精品一区二区综合av| 欧美成人久久| 欧美一区二区三区在线| 老鸭窝亚洲一区二区三区| 亚洲午夜视频在线| 久久一区精品| 欧美自拍偷拍午夜视频| 欧美黄色大片网站| 久久综合久色欧美综合狠狠| 欧美伦理在线观看| 久久频这里精品99香蕉| 欧美视频在线观看免费网址| 麻豆精品精品国产自在97香蕉| 国产精品久久久久av免费| 欧美成人乱码一区二区三区| 国产精品一区2区| 亚洲麻豆av| 亚洲国产综合在线看不卡| 亚洲欧美一级二级三级| 中文精品视频一区二区在线观看| 久久综合给合| 久久久水蜜桃| 国产色产综合色产在线视频| 一本到高清视频免费精品| 亚洲欧洲免费视频| 久久久久久久综合狠狠综合| 午夜精品在线观看| 欧美丝袜一区二区| 日韩视频免费观看高清完整版| 在线播放精品| 久久久久国产精品一区| 久久九九国产精品怡红院| 国产精品一区二区久久| 亚洲天堂视频在线观看| 亚洲一区bb| 国产精品成人va在线观看| 亚洲精品一区二区在线观看| 亚洲精品在线视频| 欧美精品aa| 野花国产精品入口| 午夜久久久久久久久久一区二区| 亚洲精品久久视频| 欧美激情网友自拍| 亚洲国产视频a| 亚洲黑丝在线| 欧美精品首页| 夜夜嗨av一区二区三区四区| 国产精品99久久久久久久久| 欧美日韩高清在线观看| 99re6热只有精品免费观看| 99精品欧美一区| 欧美日韩中文字幕| 亚洲综合国产精品| 久久综合99re88久久爱| 亚洲福利久久| 欧美日韩国产精品一卡| 正在播放欧美视频| 久久精品视频网| 在线看片欧美| 欧美日韩国产在线看| 亚洲欧美日韩国产一区二区三区| 久久精品免费观看| 亚洲激情在线观看| 国产精品久久九九| 久久久久久亚洲精品杨幂换脸| 欧美mv日韩mv国产网站| 夜夜嗨av一区二区三区网页 | 久久精品综合一区| 国产欧美日韩在线视频| 亚洲国产欧美不卡在线观看| 巨胸喷奶水www久久久免费动漫| 一区二区电影免费观看| 久久午夜羞羞影院免费观看| 亚洲一区二区三区高清| 免费成人高清视频| 午夜精品在线观看| 国产精品高潮呻吟久久| 亚洲精品国产精品久久清纯直播 | 最新国产精品拍自在线播放| 国产免费成人av| 亚洲精品日韩在线观看| 亚洲第一免费播放区| 久久大逼视频| 午夜精品视频在线观看一区二区 | 亚洲精品久久久久久下一站| 欧美777四色影视在线| 久久av一区二区三区漫画| 欧美成人一二三| 亚洲图片欧美午夜| 在线欧美亚洲| 国产欧美精品一区| 欧美日韩极品在线观看一区| 久久久久看片| 免费欧美电影| 免费国产一区二区| 亚洲字幕一区二区| 亚洲精品视频在线播放| 欧美 日韩 国产在线|