Interaktywne akcje skryptowe
Wprowadzenie
Dział zatytułowany „Wprowadzenie”Akcje skryptowe to skrypty, które dodają wpis do menu i/lub paska narzędzi i które mogą obsługiwać interakcje użytkownika. Akcje skryptowe pozostają aktywne, dopóki nie zostaną zakończone przez użytkownika lub dopóki nie zakończą się same.
Zdarzenia
Dział zatytułowany „Zdarzenia”Gdy tylko akcja skryptowa zostanie uruchomiona, obsługuje różne zdarzenia, dopóki nie zostanie zakończona. Zdarzenie to coś, co zachodzi, jeśli coś się dzieje. Na przykład, jeśli akcja skryptowa zostanie uruchomiona, wywoływane jest beginEvent. Jeśli użytkownik kliknie obiekt, wyzwalane jest zdarzenie pickEntity, jeśli użytkownik kliknie współrzędną, występuje zdarzenie pickCoordinate itd.
Minimalna struktura akcji skryptowej jest następująca:
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"]);};Ten przykładowy skrypt dodaje menu na dole menu Różne > Przykłady. Tekst menu to “Minimal Example”.
Zwróć uwagę, że aby skrypt został znaleziony, nazwa pliku musi odpowiadać nazwie klasy, tj. “ExMyMinimal.js” w tym przypadku. Musi również znajdować się w katalogu o tej samej nazwie “ExMyMinimal”, więc ten skrypt można na przykład umieścić w scripts/Misc/ExMyMinimal/ExMyMinimal.js.
Swoje skrypty możesz również umieścić w lokalnym folderze scripts w folderze domowym użytkownika. Aby poznać dokładny folder, otwórz okno dialogowe „O programie” (Pomoc > O QCAD…) i przejdź na kartę System. Zobaczysz tam lokalizację danych w pozycji Data directory. To katalog, w którym musisz utworzyć podfolder o nazwie scripts, a w nim podfoldery, po jednym folderze na każde narzędzie skryptowe, na przykład /ścieżka/do/katalogu danych/scripts/MyScripts/MyScript1/MyScript1.js
Dokładna lokalizacja zależy od systemu i jego konfiguracji.
Dodawanie beginEvent
Dział zatytułowany „Dodawanie beginEvent”Powyższy skrypt jest w pełni funkcjonalny i można go uruchomić. Jednak po uruchomieniu w rzeczywistości nic nie robi. Ponadto, po uruchomieniu skrypt pozostaje aktywny, dopóki użytkownik go nie zakończy, klikając prawym przyciskiem myszy. Aby to zmienić, zaimplementujmy beginEvent, aby wypisać coś w historii wiersza poleceń QCAD i zakończyć akcję:
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"]);};Jeśli narzędzie Różne > Przykłady > Minimal Example zostanie teraz uruchomione, wypisze “Hello World!” w historii wiersza poleceń (wiersz 12), a następnie zakończy się (wiersz 14).
Jeśli skrypt nie wymaga żadnej interakcji użytkownika, taki skrypt można wykorzystać do dodania menu, które coś robi, a następnie kończy się. Przykładami takich akcji są Widok > Automatyczne powiększenie, Wybierz > Wybierz wszystko, Edytuj > Usuń itd.
Dodawanie interakcji
Dział zatytułowany „Dodawanie interakcji”Gdy tylko skrypt wymaga jakiegokolwiek rodzaju interakcji użytkownika, musimy zaimplementować więcej procedur obsługi zdarzeń i powiedzieć skryptowi, co użytkownik musi zrobić dalej (np. wybrać obiekt lub zdefiniować współrzędną). W następnym kroku wchodzimy w stan, w którym akcja oczekuje współrzędnej od użytkownika. Następnie rysujemy okrąg w każdej pozycji, którą użytkownik kliknie lub wprowadzi.
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"]);};W beginEvent nie kończymy już akcji natychmiast, lecz pozwalamy jej działać, dopóki użytkownik jej nie zakończy (kliknięcie prawym przyciskiem lub Escape). Następnie implementujemy pickCoordinate, aby zapisać pozycję kursora myszy lub wprowadzoną współrzędną i albo zaktualizować podgląd, albo zastosować operację (tj. dodać okrąg). pickCoordinate jest wywoływane za każdym razem, gdy użytkownik porusza myszą, aby wyświetlić podgląd planowanej operacji. Gdy użytkownik kliknie lub wprowadzi współrzędną, jest wywoływane z parametrem preview ustawionym na false, aby wskazać, że wybrano lub wprowadzono ostateczną współrzędną.
updatePreview w wierszu 22 wyświetla podgląd operacji zwróconej przez getOperation, podczas gdy applyOperation w wierszu 25 faktycznie stosuje operację do naszego dokumentu.
getOperation musi zostać zaimplementowana tak, aby zwracała operację do podglądu lub zastosowania w dokumencie. Jest to nieco bardziej złożone niż to, co widzieliśmy w prostym API powyżej. Dzieje się tak, ponieważ pojedyncza operacja może być użyta do dodania wielu obiektów, modyfikacji obiektów lub usunięcia obiektów.
Dodawanie widżetów do paska narzędzi opcji
Dział zatytułowany „Dodawanie widżetów do paska narzędzi opcji”Okrąg narysowany w naszym przykładzie ma zawsze promień 1 jednostki rysunkowej (zobacz wiersz 33). W kolejnym kroku chcemy umożliwić użytkownikowi wprowadzenie promienia okręgu. QCAD zazwyczaj używa paska narzędzi opcji u góry do wyświetlania i zmiany takich parametrów narzędzia. W tym celu musimy zdefiniować, które widżety chcemy pokazać na pasku narzędzi opcji i jakie parametry kontrolują. Można to zrobić za pomocą pliku UI, pliku XML, który definiuje widżet i jego zawartość. Pliki UI można wygodnie projektować za pomocą oprogramowania o nazwie Qt Designer, które jest częścią zestawu narzędzi Qt. W tym przykładzie używamy prostego pliku UI, który można również utworzyć w edytorze tekstu (plik 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>Plik UI definiuje dwa widżety: etykietę (QLabel) i pole edycji wiersza (RMathLineEdit). Ważna jest nazwa pola edycji wiersza (“Radius”). Widżet jest automatycznie łączony z naszym skryptem poprzez tę nazwę. Wszystko, co musimy zrobić w naszym skrypcie, to zdefiniować, którego pliku UI chcemy użyć (wiersz 9), i zaimplementować nową procedurę obsługi zdarzeń o nazwie slotRadiusChanged, czyli “slot” + [nazwa naszego pola edycji wiersza] + “Changed” (wiersz 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"]);};Ta nowa funkcja slotRadiusChanged jest wywoływana za każdym razem, gdy użytkownik wprowadza nowy promień. Ustawia zmienną składową this.radius, która z kolei jest używana podczas tworzenia okręgu w getOperation.
Wszystkie skrypty w QCAD są oparte na jednej z tych koncepcji przedstawionych w tym samouczku.
Ponieważ każde narzędzie w QCAD jest zaimplementowane jako skrypt na najwyższym poziomie, dostępnych jest wiele przykładowych skryptów. Możesz je znaleźć w naszym repozytorium git.