Skip to content

Aksi Skrip Interaktif

Aksi skrip adalah skrip yang menambahkan sebuah entri ke menu dan/atau bilah alat dan yang dapat menangani interaksi pengguna. Aksi skrip tetap aktif sampai diakhiri oleh pengguna atau sampai ia mengakhiri dirinya sendiri.

Segera setelah aksi skrip dimulai, ia menangani berbagai peristiwa sampai diakhiri. Sebuah peristiwa adalah sesuatu yang terjadi apabila sesuatu sedang berlangsung. Misalnya, jika aksi skrip dimulai, beginEvent dipanggil. Jika pengguna mengklik sebuah entitas, peristiwa pickEntity dipicu, jika pengguna mengklik sebuah koordinat, peristiwa pickCoordinate terjadi, dan seterusnya.

Struktur minimal sebuah aksi skrip adalah sebagai berikut:

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"]);
};

Skrip contoh ini menambahkan sebuah menu di bagian bawah menu Lain-lain > Contoh. Teks menunya adalah “Minimal Example”.

Perhatikan bahwa agar skrip dapat ditemukan, nama berkas harus cocok dengan nama kelas, yaitu “ExMyMinimal.js” dalam kasus ini. Ia juga harus berada di dalam direktori dengan nama yang sama “ExMyMinimal”, sehingga skrip ini misalnya dapat ditempatkan di scripts/Misc/ExMyMinimal/ExMyMinimal.js.

Anda juga dapat menempatkan skrip Anda ke dalam folder scripts lokal di dalam folder home pengguna Anda. Untuk mengetahui folder yang tepat, buka dialog tentang program (Bantuan > Tentang QCAD…) dan buka tab Sistem. Di sana Anda dapat melihat lokasi data pada Data directory. Ini adalah direktori tempat Anda harus membuat subfolder bernama scripts beserta subfolder di dalamnya, satu folder untuk setiap alat skrip, misalnya /jalur/ke/direktori data/scripts/MyScripts/MyScript1/MyScript1.js

Lokasi persisnya bergantung pada sistem dan konfigurasinya.

Skrip di atas berfungsi penuh dan dapat dipicu. Namun, ia sebenarnya tidak melakukan apa pun ketika dipicu. Selain itu, setelah dipicu, skrip tetap aktif sampai pengguna mengakhirinya dengan mengklik tombol kanan mouse. Untuk mengubah ini, mari kita implementasikan beginEvent untuk menampilkan sesuatu ke riwayat baris perintah QCAD dan mengakhiri aksi:

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"]);
};

Jika alat Lain-lain > Contoh > Minimal Example kini dijalankan, ia menampilkan “Hello World!” ke riwayat baris perintah (baris 12) lalu mengakhiri dirinya (baris 14).

Jika sebuah skrip tidak memerlukan interaksi pengguna apa pun, skrip semacam itu dapat digunakan untuk menambahkan sebuah menu yang melakukan sesuatu lalu mengakhiri dirinya. Contoh aksi semacam ini adalah Melihat > Zoom Otomatis, Pilih > Pilih Semua, Sunting > Menghapus, dan sebagainya.

Segera setelah sebuah skrip memerlukan interaksi pengguna dalam bentuk apa pun, kita perlu mengimplementasikan lebih banyak penangan peristiwa dan memberi tahu skrip apa yang perlu dilakukan pengguna selanjutnya (mis. memilih sebuah entitas atau mendefinisikan sebuah koordinat). Pada langkah berikutnya, kita memasuki suatu keadaan di mana aksi mengharapkan sebuah koordinat dari pengguna. Kemudian kita menggambar sebuah lingkaran di setiap posisi yang diklik atau dimasukkan pengguna.

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"]);
};

Pada beginEvent, kita tidak lagi mengakhiri aksi seketika, melainkan membiarkannya berjalan sampai pengguna mengakhirinya (klik kanan atau Escape). Kemudian kita mengimplementasikan pickCoordinate untuk menyimpan posisi kursor mouse atau koordinat yang dimasukkan dan untuk memperbarui pratinjau atau menerapkan operasi (yaitu menambahkan lingkaran). pickCoordinate dipanggil setiap kali pengguna menggerakkan mouse untuk menampilkan pratinjau operasi yang direncanakan. Ketika pengguna mengklik atau memasukkan sebuah koordinat, fungsi ini dipanggil dengan parameter preview disetel ke false untuk menunjukkan bahwa sebuah koordinat definitif telah dipilih atau dimasukkan.

updatePreview pada baris 22 menampilkan pratinjau operasi yang dikembalikan oleh getOperation, sedangkan applyOperation pada baris 25 benar-benar menerapkan operasi ke dokumen kita.

getOperation harus diimplementasikan untuk mengembalikan operasi yang akan dipratinjau atau diterapkan pada dokumen. Ini sedikit lebih kompleks daripada apa yang telah kita lihat pada API sederhana di atas. Hal ini karena sebuah operasi tunggal dapat digunakan untuk menambahkan beberapa objek, memodifikasi objek, atau menghapus objek.

Lingkaran yang digambar pada contoh kita selalu memiliki radius 1 satuan gambar (lihat baris 33). Pada langkah berikutnya, kita ingin mengizinkan pengguna memasukkan radius untuk lingkaran tersebut. QCAD biasanya menggunakan bilah alat opsi di bagian atas untuk menampilkan dan mengubah parameter alat semacam itu. Untuk ini, kita perlu mendefinisikan widget apa yang ingin kita tampilkan di bilah alat opsi dan parameter apa yang mereka kendalikan. Ini dapat dilakukan dengan berkas UI, sebuah berkas XML yang mendefinisikan sebuah widget beserta isinya. Berkas UI dapat dirancang dengan nyaman menggunakan perangkat lunak bernama Qt Designer yang merupakan bagian dari toolkit Qt. Untuk contoh ini, kita menggunakan berkas UI sederhana yang juga dapat dibuat di editor teks (berkas 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>&amp;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>

Berkas UI mendefinisikan dua widget: sebuah label (QLabel) dan sebuah baris edit (RMathLineEdit). Yang penting adalah nama baris edit (“Radius”). Widget secara otomatis ditautkan ke skrip kita melalui nama ini. Yang perlu kita lakukan di skrip hanyalah mendefinisikan berkas UI mana yang ingin kita gunakan (baris 9) dan mengimplementasikan penangan peristiwa baru bernama slotRadiusChanged, yaitu “slot” + [nama baris edit kita] + “Changed” (baris 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"]);
};

Fungsi baru slotRadiusChanged ini dipanggil setiap kali pengguna memasukkan radius baru. Ia menyetel variabel anggota this.radius yang selanjutnya digunakan saat membuat lingkaran di getOperation.

Semua skrip di QCAD didasarkan pada salah satu konsep yang diuraikan dalam tutorial ini.

Karena setiap alat di QCAD diimplementasikan sebagai skrip pada tingkat teratas, tersedia banyak skrip contoh. Anda dapat menemukannya di repositori git kami.