Etkileşimli Betik Eylemleri
Betik eylemleri, bir menüye ve/veya araç çubuğuna bir giriş ekleyen ve kullanıcı etkileşimlerini işleyebilen betiklerdir. Betik eylemleri, kullanıcı tarafından sonlandırılana veya kendileri sonlanana kadar etkin kalır.
Olaylar
Section titled “Olaylar”Betik eylemi başlatılır başlatılmaz, sonlandırılana kadar çeşitli olayları işler. Bir olay, bir şey olduğunda ortaya çıkan bir şeydir. Örneğin, betik eylemi başlatılırsa, beginEvent çağrılır. Kullanıcı bir nesneye tıklarsa bir pickEntity olayı tetiklenir, kullanıcı bir koordinata tıklarsa bir pickCoordinate olayı oluşur vb.
Bir betik eyleminin minimal yapısı aşağıdaki gibidir:
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"]);};Bu örnek betik, Çeşitli > Örnekler menüsünün altına bir menü ekler. Menü metni “Minimal Example”dır.
Betiğin bulunabilmesi için dosya adının sınıf adıyla eşleşmesi gerektiğini unutmayın, yani bu durumda “ExMyMinimal.js”. Ayrıca aynı adı taşıyan bir dizinin içinde bulunması gerekir “ExMyMinimal”, bu nedenle bu betik örneğin scripts/Misc/ExMyMinimal/ExMyMinimal.js içine konulabilir.
Betiklerinizi ayrıca kullanıcı giriş klasörünüzdeki yerel bir scripts klasörüne de koyabilirsiniz. Tam klasörü öğrenmek için hakkında iletişim kutusunu (Yardım > QCAD Hakkında…) açın ve Sistem sekmesine gidin. Orada veri konumunu Data directory altında görebilirsiniz. Bu, altında scripts adlı bir alt klasör ve onun içinde her betik aracı için birer alt klasör oluşturmanız gereken dizindir, örneğin /veri dizinine/giden/yol/scripts/MyScripts/MyScript1/MyScript1.js
Tam konum, sisteminize ve yapılandırmasına bağlıdır.
beginEvent Ekleme
Section titled “beginEvent Ekleme”Yukarıdaki betik tamamen işlevseldir ve tetiklenebilir. Ancak, tetiklendiğinde aslında hiçbir şey yapmaz. Ayrıca, bir kez tetiklendiğinde, betik, kullanıcı sağ fare düğmesine tıklayarak sonlandırana kadar etkin kalır. Bunu değiştirmek için, QCAD’in komut satırı geçmişine bir şey yazdırması ve eylemi sonlandırması için beginEvent’i uygulayalım:
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"]);};Çeşitli > Örnekler > Minimal Example aracı şimdi başlatılırsa, komut satırı geçmişine “Hello World!” yazdırır (satır 12) ve ardından sonlanır (satır 14).
Bir betik herhangi bir kullanıcı etkileşimi gerektirmiyorsa, böyle bir betik, bir şey yapan ve ardından sonlanan bir menü eklemek için kullanılabilir. Bu tür eylemlere örnekler Görünüm > Otomatik Yakınlaştırma, Seç > Tümünü Seç, Düzen > Sil vb.
Etkileşim Ekleme
Section titled “Etkileşim Ekleme”Bir betik herhangi bir tür kullanıcı etkileşimi gerektirir gerektirmez, daha fazla olay işleyicisi uygulamamız ve betiğe kullanıcının bundan sonra ne yapması gerektiğini (örneğin bir nesne seçme veya bir koordinat tanımlama) söylememiz gerekir. Sonraki adımda, eylemin kullanıcıdan bir koordinat beklediği bir duruma gireriz. Ardından kullanıcının tıkladığı veya girdiği her konumda bir daire çizeriz.
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"]);};beginEvent’te artık eylemi hemen sonlandırmayız, ancak kullanıcı onu sonlandırana kadar (sağ tıklama veya Escape) çalışmasına izin veririz. Ardından, fare imlecinin konumunu veya girilen koordinatı depolamak ve önizlemeyi güncellemek ya da işlemi uygulamak (yani daireyi eklemek) için pickCoordinate’i uygularız. pickCoordinate, kullanıcı planlanan işlemin bir önizlemesini görüntülemek için fareyi her hareket ettirdiğinde çağrılır. Kullanıcı bir koordinata tıkladığında veya girdiğinde, kesin bir koordinatın seçildiğini veya girildiğini belirtmek için preview parametresi false olarak ayarlanmış olarak çağrılır.
Satır 22’deki updatePreview, getOperation tarafından döndürülen işlemi önizlerken, satır 25’teki applyOperation işlemi belgemize gerçekten uygular.
getOperation, belgeye önizlenecek veya uygulanacak işlemi döndürmek için uygulanmalıdır. Bu, yukarıdaki basit API’de gördüğümüzden biraz daha karmaşıktır. Bunun nedeni, tek bir işlemin birden fazla nesne eklemek, nesneleri değiştirmek veya nesneleri silmek için kullanılabilmesidir.
Seçenekler Araç Çubuğuna Widget Ekleme
Section titled “Seçenekler Araç Çubuğuna Widget Ekleme”Örneğimizde çizilen dairenin yarıçapı her zaman 1 çizim birimidir (bkz. satır 33). Sonraki bir adımda, kullanıcının daire için bir yarıçap girmesine izin vermek istiyoruz. QCAD, genellikle bu tür araç parametrelerini görüntülemek ve değiştirmek için üstteki seçenekler araç çubuğunu kullanır. Bunun için, seçenekler araç çubuğunda hangi widget’ları göstermek istediğimizi ve hangi parametreleri kontrol ettiklerini tanımlamamız gerekir. Bu, bir widget’ı ve içeriğini tanımlayan bir UI dosyası, bir XML dosyası ile yapılabilir. UI dosyaları, Qt araç setinin bir parçası olarak gelen Qt Designer adlı bir yazılım kullanılarak rahatça tasarlanabilir. Bu örnek için, bir metin düzenleyicide de oluşturulabilen basit bir UI dosyası kullanıyoruz (dosya 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>UI dosyası iki widget tanımlar: bir etiket (QLabel) ve bir satır düzenleme alanı (RMathLineEdit). Önemli olan satır düzenleme alanının adıdır (“Radius”). Widget, bu ad aracılığıyla betiğimize otomatik olarak bağlanır. Betiğimizde yapmamız gereken tek şey, hangi UI dosyasını kullanmak istediğimizi tanımlamak (satır 9) ve slotRadiusChanged adlı yeni bir olay işleyicisi uygulamaktır, yani “slot” + [satır düzenleme alanımızın adı] + “Changed” (satır 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"]);};Bu yeni slotRadiusChanged fonksiyonu, kullanıcı her yeni bir yarıçap girdiğinde çağrılır. this.radius üye değişkenini ayarlar; bu değişken de getOperation’da daire oluşturulurken kullanılır.
QCAD’deki tüm betikler, bu öğreticide özetlenen kavramlardan birine dayanır.
QCAD’deki her araç en üst düzeyde bir betik olarak uygulandığından, çok sayıda örnek betik mevcuttur. Bunları git deposumuzda bulabilirsiniz.