Acțiuni de script interactive
Introducere
Section titled “Introducere”Acțiunile de script sunt scripturi care adaugă o intrare la un meniu și/sau o bară de instrumente și care pot gestiona interacțiunile cu utilizatorul. Acțiunile de script rămân active până când sunt terminate de utilizator sau până când se termină singure.
Evenimente
Section titled “Evenimente”De îndată ce acțiunea de script este pornită, ea gestionează diverse evenimente până când este terminată. Un eveniment este ceva care apare dacă se întâmplă ceva. De exemplu, dacă acțiunea de script este pornită, este apelat beginEvent. Dacă utilizatorul face clic pe o entitate, este declanșat un eveniment pickEntity, dacă utilizatorul face clic pe o coordonată, apare un eveniment pickCoordinate etc.
Structura minimă a unei acțiuni de script este următoarea:
include("scripts/EAction.js");
function ExMyMinimal(guiAction) { EAction.call(this, guiAction);}
ExMyMinimal.prototype = new EAction();
ExMyMinimal.init = function(basePath) { var action = new RGuiAction(qsTr("&Minimal Example"), RMainWindowQt.getMainWindow()); action.setRequiresDocument(true); action.setScriptFile(basePath + "/ExMyMinimal.js"); action.setGroupSortOrder(100000); action.setSortOrder(0); action.setWidgetNames(["ExamplesMenu"]);};Acest script exemplu adaugă un meniu în partea de jos a meniului Diverse > Exemple. Textul meniului este “Minimal Example”.
Rețineți că, pentru ca scriptul să fie găsit, numele fișierului trebuie să corespundă numelui clasei, adică “ExMyMinimal.js” în acest caz. De asemenea, trebuie să se afle într-un director cu același nume “ExMyMinimal”, astfel încât acest script poate fi plasat, de exemplu, în scripts/Misc/ExMyMinimal/ExMyMinimal.js.
De asemenea, vă puteți plasa scripturile într-un folder local scripts din folderul dumneavoastră personal. Pentru a afla folderul exact, deschideți fereastra de dialog „Despre” (Ajutor > Despre QCAD…) și mergeți la fila Sistem. Acolo puteți vedea locația datelor la Data directory. Acesta este directorul în care trebuie să creați un subfolder numit scripts, iar în acesta subfoldere, câte un folder pentru fiecare instrument de script, de exemplu /cale/către/directorul de date/scripts/MyScripts/MyScript1/MyScript1.js
Locația exactă depinde de sistemul dumneavoastră și de configurația acestuia.
Adăugarea beginEvent
Section titled “Adăugarea beginEvent”Scriptul de mai sus este pe deplin funcțional și poate fi declanșat. Cu toate acestea, nu face de fapt nimic când este declanșat. În plus, odată declanșat, scriptul rămâne activ până când utilizatorul îl termină făcând clic pe butonul drept al mouse-ului. Pentru a schimba acest lucru, să implementăm beginEvent pentru a afișa ceva în istoricul liniei de comandă a QCAD și pentru a termina acțiunea:
include("scripts/EAction.js");
function ExMyMinimal(guiAction) { EAction.call(this, guiAction);}
ExMyMinimal.prototype = new EAction();
ExMyMinimal.prototype.beginEvent = function() { EAction.prototype.beginEvent.call(this);
EAction.handleUserMessage("Hello World!");
this.terminate();};
ExMyMinimal.init = function(basePath) { var action = new RGuiAction(qsTr("&Minimal Example"), RMainWindowQt.getMainWindow()); action.setRequiresDocument(true); action.setScriptFile(basePath + "/ExMyMinimal.js"); action.setGroupSortOrder(100000); action.setSortOrder(0); action.setWidgetNames(["ExamplesMenu"]);};Dacă instrumentul Diverse > Exemple > Minimal Example este pornit acum, afișează “Hello World!” în istoricul liniei de comandă (linia 12) și apoi se termină (linia 14).
Dacă un script nu necesită nicio interacțiune cu utilizatorul, un astfel de script poate fi folosit pentru a adăuga un meniu care face ceva și apoi se termină. Exemple de astfel de acțiuni sunt Vezi > Zoom automat, Selectează > Selectează tot, Editare > Șterge etc.
Adăugarea interacțiunii
Section titled “Adăugarea interacțiunii”De îndată ce un script necesită orice fel de interacțiune cu utilizatorul, trebuie să implementăm mai multe gestionare de evenimente și să îi spunem scriptului ce trebuie să facă utilizatorul în continuare (de ex. selectarea unei entități sau definirea unei coordonate). În pasul următor, intrăm într-o stare în care acțiunea așteaptă o coordonată de la utilizator. Apoi desenăm un cerc la fiecare poziție pe care utilizatorul face clic sau o introduce.
include("scripts/EAction.js");
function ExMyMinimal(guiAction) { EAction.call(this, guiAction);
this.pos = undefined;}
ExMyMinimal.prototype = new EAction();
ExMyMinimal.prototype.beginEvent = function() { EAction.prototype.beginEvent.call(this);
var di = this.getDocumentInterface(); di.setClickMode(RAction.PickCoordinate);};
ExMyMinimal.prototype.pickCoordinate = function(event, preview) { this.pos = event.getModelPosition();
if (preview) { this.updatePreview(); } else { this.applyOperation(); }};
ExMyMinimal.prototype.getOperation = function(preview) { var doc = this.getDocument();
var op = new RAddObjectOperation(); var circle = new RCircle(this.pos, 1); op.addObject(shapeToEntity(doc, circle)); return op;};
ExMyMinimal.init = function(basePath) { var action = new RGuiAction(qsTr("&Minimal Example"), RMainWindowQt.getMainWindow()); action.setRequiresDocument(true); action.setScriptFile(basePath + "/ExMyMinimal.js"); action.setGroupSortOrder(100000); action.setSortOrder(0); action.setWidgetNames(["ExamplesMenu"]);};În beginEvent, nu mai terminăm acțiunea imediat, ci o lăsăm să ruleze până când utilizatorul o termină (clic dreapta sau Escape). Apoi implementăm pickCoordinate pentru a stoca poziția cursorului mouse-ului sau coordonata introdusă și pentru a actualiza fie previzualizarea, fie a aplica operațiunea (adică a adăuga cercul). pickCoordinate este apelat ori de câte ori utilizatorul mișcă mouse-ul pentru a afișa o previzualizare a operațiunii planificate. Când utilizatorul face clic sau introduce o coordonată, este apelat cu parametrul preview setat la false pentru a indica faptul că a fost aleasă sau introdusă o coordonată definitivă.
updatePreview de la linia 22 previzualizează operațiunea returnată de getOperation, în timp ce applyOperation de la linia 25 aplică efectiv operațiunea documentului nostru.
getOperation trebuie implementată pentru a returna operațiunea de previzualizat sau de aplicat documentului. Acest lucru este puțin mai complex decât ceea ce am văzut în API-ul simplu de mai sus. Aceasta pentru că o singură operațiune poate fi folosită pentru a adăuga mai multe obiecte, a modifica obiecte sau a șterge obiecte.
Adăugarea widgeturilor în bara de instrumente de opțiuni
Section titled “Adăugarea widgeturilor în bara de instrumente de opțiuni”Cercul desenat în exemplul nostru are întotdeauna o rază de 1 unitate de desen (vedeți linia 33). Într-un pas următor, dorim să permitem utilizatorului să introducă o rază pentru cerc. QCAD folosește de obicei bara de instrumente de opțiuni din partea de sus pentru a afișa și modifica astfel de parametri ai instrumentului. Pentru aceasta, trebuie să definim ce widgeturi dorim să afișăm în bara de instrumente de opțiuni și ce parametri controlează. Acest lucru se poate face cu un fișier UI, un fișier XML care definește un widget și conținutul său. Fișierele UI pot fi proiectate confortabil folosind un software numit Qt Designer, care vine ca parte a setului de instrumente Qt. Pentru acest exemplu, folosim un fișier UI simplu care poate fi creat și într-un editor de text (fișier ExMyMinimal.ui):
<?xml version="1.0" encoding="UTF-8"?><ui version="4.0"> <class>ExMyMinimal</class> <widget class="QWidget" name="ExMyMinimal"> <layout class="QHBoxLayout"> <item> <widget class="QLabel" name="RadiusLabel"> <property name="text"> <string>&Radius:</string> </property> <property name="buddy"> <cstring>Radius</cstring> </property> </widget> </item> <item> <widget class="RMathLineEdit" name="Radius"> <property name="text"> <string notr="true">1</string> </property> </widget> </item> </layout> </widget> <customwidgets> <customwidget> <class>RMathLineEdit</class> <extends>QLineEdit</extends> <header>RMathLineEdit.h</header> </customwidget> </customwidgets> <resources/> <connections/></ui>Fișierul UI definește două widgeturi: o etichetă (QLabel) și un câmp de editare pe o linie (RMathLineEdit). Important este numele câmpului de editare pe o linie (“Radius”). Widgetul este legat automat de scriptul nostru prin acest nume. Tot ce trebuie să facem în scriptul nostru este să definim ce fișier UI dorim să folosim (linia 9) și să implementăm un nou gestionar de evenimente numit slotRadiusChanged, adică “slot” + [numele câmpului nostru de editare pe o linie] + “Changed” (linia 45):
include("scripts/EAction.js");
function ExMyMinimal(guiAction) { EAction.call(this, guiAction);
this.pos = undefined; this.radius = undefined;
this.setUiOptions("ExMyMinimal.ui");}
ExMyMinimal.prototype = new EAction();
ExMyMinimal.prototype.beginEvent = function() { EAction.prototype.beginEvent.call(this);
var di = this.getDocumentInterface(); di.setClickMode(RAction.PickCoordinate);};
ExMyMinimal.prototype.pickCoordinate = function(event, preview) { this.pos = event.getModelPosition();
if (preview) { this.updatePreview(); } else { this.applyOperation(); }};
ExMyMinimal.prototype.getOperation = function(preview) { if (isNull(this.pos) || isNull(this.radius)) { return undefined; }
var doc = this.getDocument();
var op = new RAddObjectOperation(); var circle = new RCircle(this.pos, this.radius); op.addObject(shapeToEntity(doc, circle)); return op;};
ExMyMinimal.prototype.slotRadiusChanged = function(v) { this.radius = v; this.updatePreview();};
ExMyMinimal.init = function(basePath) { var action = new RGuiAction(qsTr("&Minimal Example"), RMainWindowQt.getMainWindow()); action.setRequiresDocument(true); action.setScriptFile(basePath + "/ExMyMinimal.js"); action.setGroupSortOrder(100000); action.setSortOrder(0); action.setWidgetNames(["ExamplesMenu"]);};Această nouă funcție slotRadiusChanged este apelată ori de câte ori utilizatorul introduce o rază nouă. Ea setează variabila membru this.radius, care este la rândul ei folosită la crearea cercului în getOperation.
Toate scripturile din QCAD se bazează pe unul dintre aceste concepte prezentate în acest tutorial.
Deoarece fiecare instrument din QCAD este implementat ca un script la nivelul superior, sunt disponibile numeroase scripturi exemplu. Le puteți găsi în depozitul nostru git.