Tutorial JavaFX: FXML dan SceneBuilder

Terjemahan Tutorial JavaFX: Artikel FXML dan SceneBuilder oleh Vojtech Ruzicka.

Cara membuat GUI dengan JavaFX menggunakan markup FXML dan SceneBuilder.

Semua posting di seri JavaFX:

  1. Tutorial JavaFX: Memulai
  2. Tutorial JavaFX: Halo dunia!
  3. Tutorial JavaFX: FXML dan SceneBuilder
  4. Tutorial JavaFX: Tata Letak Dasar
  5. Tutorial JavaFX: Tata Letak Lanjutan
  6. JavaFX Tutorial: styling CSS
  7. JavaFX Weaver: Mengintegrasikan Aplikasi JavaFX dan Spring Boot

Cara tradisional


Pada artikel sebelumnya, kami membuat aplikasi Hello World sederhana .

Hanya pengingat - kode tampak seperti ini:

@Override public void start(Stage primaryStage) throws Exception { primaryStage.setTitle("Hello world Application"); primaryStage.setWidth(300); primaryStage.setHeight(200); InputStream iconStream = getClass().getResourceAsStream("/icon.png"); Image image = new Image(iconStream); primaryStage.getIcons().add(image); Label helloWorldLabel = new Label("Hello world!"); helloWorldLabel.setAlignment(Pos.CENTER); Scene primaryScene = new Scene(helloWorldLabel); primaryStage.setScene(primaryScene); primaryStage.show(); } 

Seperti yang Anda lihat, seluruh antarmuka pengguna dibuat dalam kode Java.

Ini adalah contoh yang sangat sederhana, tetapi karena aplikasi Anda menjadi lebih kompleks, ketika Anda harus memasukkan beberapa tingkat tata letak bersarang dan banyak komponen, kode yang dihasilkan dapat menjadi sangat sulit untuk dipahami. Namun, ini tidak semua - di kelas yang sama ada kode yang bertanggung jawab atas struktur, efek visual dan perilaku pada saat yang sama.

Kelas jelas tidak memiliki tanggung jawab tunggal. Bandingkan ini, misalnya, dengan antarmuka web, di mana setiap halaman memiliki tugas yang jelas dipisahkan:

  • HTML adalah struktur
  • CSS adalah efek visual
  • JavaScript adalah perilaku

Memperkenalkan FXML


Jelas, memiliki semua kode di satu tempat bukanlah ide yang baik. Anda perlu menyusunnya agar lebih mudah dipahami dan membuatnya lebih mudah dikelola.

Pada kenyataannya, ada banyak pola desain untuk ini. Biasanya, Anda berakhir dengan opsi "Model-View-Apapun" - itu seperti "Model View Controller," "Model View Presenter," atau "Model View ViewModel."

Anda dapat menghabiskan waktu berjam-jam membahas pro dan kontra dari berbagai opsi - jangan lakukan di sini. Lebih penting lagi, dengan JavaFx Anda dapat menggunakannya.

Ini dimungkinkan karena selain desain prosedural dari antarmuka pengguna Anda, Anda dapat menggunakan markup XML deklaratif.

Ternyata struktur hierarki XML adalah cara yang bagus untuk menggambarkan hierarki komponen dalam antarmuka pengguna. HTML berfungsi dengan baik, bukan?

Format XML khusus JavaFX disebut FXML. Di dalamnya, Anda dapat menentukan semua komponen aplikasi dan propertinya, serta mengaitkannya dengan pengontrol, yang bertanggung jawab untuk mengelola interaksi.

Unduh file FXML


Jadi, bagaimana kita dapat mengubah metode peluncuran kami agar berfungsi dengan FXML?

 FXMLLoader loader = new FXMLLoader(); URL xmlUrl = getClass().getResource("/mainScene.fxml"); loader.setLocation(xmlUrl); Parent root = loader.load(); primaryStage.setScene(new Scene(root)); primaryStage.show(); 

Di sini root mewakili komponen root dari antarmuka pengguna Anda, komponen lain bersarang di dalamnya.

Metode memuat memiliki nilai pengembalian generik, sehingga Anda dapat menentukan jenis tertentu, bukan Induk . Selanjutnya, Anda mendapatkan akses ke metode berorientasi komponen. Namun, ini membuat kode Anda lebih rapuh. Jika Anda mengubah jenis komponen root di FXML Anda, aplikasi mungkin berhenti bekerja pada saat dijalankan, tetapi tidak akan ada kesalahan selama kompilasi. Ini karena sekarang ada ketidakcocokan dari tipe yang dideklarasikan di FXML Anda dan di loader Java FXML.

Buat file FXML


Sekarang kita tahu cara memuat file FXML, tetapi kita masih harus membuatnya. File harus memiliki ekstensi .fxml. Dalam proyek Maven, Anda dapat meletakkan file ini di folder sumber daya atau FXMLLoader dapat mengunduhnya dari URL eksternal.

Setelah membuat file, masukkan deklarasi XML di baris pertama:

 <?xml version="1.0" encoding="UTF-8"?> 

Impor


Sebelum Anda menambahkan masing-masing komponen ke file, Anda harus memastikan bahwa mereka dikenali dengan benar. Untuk melakukan ini, tambahkan pernyataan impor. Ini sangat mirip dengan mengimpor di kelas Java. Anda dapat mengimpor masing-masing kelas atau menggunakan wildcard seperti biasa. Mari kita lihat contoh bagian impor:
 <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> 

Berita baiknya adalah bahwa alih-alih menambahkan semua pernyataan impor secara manual, IDE Anda seharusnya membantu Anda menambahkan impor seperti menambahkannya ke kelas Java.

Menambahkan Komponen


Sekarang saatnya menambahkan beberapa komponen. Dalam artikel sebelumnya, kami mengetahui bahwa setiap adegan hanya dapat memiliki satu komponen anak. Untuk memulai, mari tambahkan label sederhana:

 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Label?> <!--      --> <Label>Hello World!</Label> 

Tentu saja, pelabelan sebagai komponen root bukan contoh yang sangat realistis. Biasanya lebih baik menggunakan semacam tata letak (layout), yang merupakan wadah untuk beberapa komponen dan mengatur pengaturannya. Kami akan membahas tata letak nanti dalam seri ini, tetapi untuk sekarang, mari kita gunakan VBox sederhana yang menempatkan anak-anaknya secara vertikal di atas satu sama lain.

 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Label?> <?import javafx.scene.layout.VBox?> <?import javafx.scene.control.Button?> <VBox> <Label text="Hello world!"/> <Label text="This is a simple demo application."/> <Button text="Click me!"/> </VBox> 

FX Namespace


Ada beberapa elemen dan atribut FXML yang tidak tersedia secara default. Anda perlu menambahkan Namespace FXML untuk membuatnya tersedia. Itu harus ditambahkan ke komponen root:

 <?xml version="1.0" encoding="UTF-8"?> ... <VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"> ... </VBox> 

Sekarang Anda dapat menggunakan elemen baru dari namespace fx. Mari coba tambahkan pengidentifikasi unik ke komponen kami:

 <Label fx:id="mainTitle" text="Hello world!"/> 

Atribut fx: id adalah pengidentifikasi unik untuk komponen yang dapat digunakan untuk merujuk ke komponen dari bagian lain dari FXML kami dan bahkan dari pengontrol kami.

Skrip


Aplikasi kami masih statis. Ada beberapa label dan tombol, tetapi aplikasi tidak melakukan apa pun yang dinamis.

Mari kita menanggapi klik tombol kita dan mengubah judul dari "Klik saya!" Untuk "Klik saya lagi!".

Hal pertama yang harus dilakukan adalah menambahkan event handler onAction untuk tombol kita.

 <Button fx:id="mainButton" text="Click me!" onAction="buttonClicked()"/> 

Perhatikan fx: id, ini adalah pengidentifikasi yang akan digunakan nanti untuk merujuk ke tombol.

Sekarang Anda perlu menyediakan fungsi yang akan dipanggil untuk menangani acara tersebut. Itu dapat didefinisikan di dalam tag skrip fx :. Yang penting adalah Anda bisa menggunakan bahasa yang berbeda untuk menulis skrip, JavaScript, Groovy atau Clojure. Mari kita lihat contoh dalam JavaScript:



Perhatikan bahwa kami merujuk ke komponen Tombol kami menggunakan pengidentifikasi mainButton, yang dinyatakan seperti ini:

 fx:id = "mainButton" 

Anda juga harus menunjukkan bahasa skrip mana yang Anda gunakan dalam file FXML:

 <?language javascript?> 

Mari kita lihat teks lengkap dari contoh ini:



Haruskah saya menggunakan ini?


Contoh di atas menunjukkan cara merujuk komponen menggunakan fx: id dan cara menambahkan perilaku sederhana menggunakan skrip JavaScript. Benarkah itu yang seharusnya Anda lakukan?

Jawabannya adalah dalam kebanyakan kasus tidak. Ada beberapa masalah dengan pendekatan ini. Alasan FXML diperkenalkan adalah pemisahan kepentingan - untuk memisahkan struktur dan perilaku antarmuka pengguna. Dalam skrip ini, perilaku yang digabungkan dengan struktur antarmuka pengguna kembali lagi. Selain itu, karena kita tidak lagi bekerja dengan kode Java, tetapi dengan XML, semua pemeriksaan kode pada waktu kompilasi dan keamanan tipe hilang. Sekarang semua masalah dalam aplikasi akan terdeteksi pada saat runtime, dan bukan pada waktu kompilasi. Aplikasi menjadi sangat rapuh dan rentan kesalahan.

Menambahkan Kontroler


Jadi apa yang bisa dilakukan untuk mendapatkan pemisahan kepentingan yang jelas? Anda dapat menautkan pengontrol ke file FXML kami. Pengontrol adalah kelas Java yang bertanggung jawab untuk menangani perilaku dan interaksi pengguna dalam suatu aplikasi. Dengan cara ini Anda dapat mengembalikan keamanan jenis dan pemeriksaan waktu kompilasi.

Pengontrol adalah POJO, ia tidak boleh memperluas atau mengimplementasikan apa pun, juga tidak memiliki penjelasan khusus.

Bagaimana saya bisa mengaitkan kelas pengontrol dengan FXML kami? Pada dasarnya ada dua opsi.

Di jawa


Anda bisa membuat instance controller sendiri atau menggunakan metode lain untuk membuat instance, seperti injeksi ketergantungan. Maka cukup unduh FXMLLoader Anda.

 FXMLLoader loader = new FXMLLoader(); loader.setController(new MainSceneController()); 

Di FXML


Anda dapat menentukan kelas controller Anda sebagai atribut fx: controller , yang harusnya terletak di komponen root.

 <VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.vojtechruzicka.MainSceneController"> ... </VBox> 

Jika Anda mendeklarasikan kelas Kontroler Anda di FXML, itu dibuat secara otomatis untuk Anda. Pendekatan ini memiliki satu batasan - di controller Anda perlu membuat konstruktor tanpa argumen untuk membuatnya mudah untuk membuat instance baru dari kelas Controller.

Untuk mengakses instance pengontrol yang dibuat secara otomatis, Anda dapat menggunakan loader FXML:

 FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/mainScene.fxml")); MainSceneController controller = loader.getController(); 

Metode Kontrol Panggilan


Sekarang Anda memiliki controller, Anda dapat menghapus skrip dan mengimplementasikan logika untuk menekan tombol langsung di controller:

 public class MainSceneController { public void buttonClicked() { System.out.println("Button clicked!"); } } 

Langkah selanjutnya adalah mendaftarkan panggilan metode ini sebagai pengendali event onAction tombol kami. Untuk merujuk pada metode dari controller kita, kita perlu menggunakan tanda # di depan nama metode:

 <VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.vojtechruzicka.MainSceneController"> <Label fx:id="mainTitle" text="Hello world!"/> <Label fx:id="subTitle" text="This is a simple demo application."/> <Button fx:id="mainButton" text="Click me!" onAction="#buttonClicked"/> </VBox> 

Ketika sebuah tombol diklik, ia memanggil metode MainSceneController.buttonClicked () . Perlu diingat bahwa ini hanya berfungsi jika metode ini dinyatakan publik. Jika pengubah akses lebih ketat, Anda harus membuat anotasi metode dengan anotasi @FXML .

 @FXML private void buttonClicked() { System.out.println("Button clicked!"); } 

Menanamkan komponen dalam pengontrol


Sejauh ini, kami hanya mencetak ke konsol. Bagaimana jika kita ingin mengubah teks tombol kita menjadi " Klik saya lagi " lagi ? Bagaimana kita bisa mendapatkan tautan ke komponen di controller kita?

Untungnya, ini mudah. Ingat atribut fx: id ini ?

 <Button fx:id="mainButton" text="Click me!" onAction="#buttonClicked"/> 

JavaFX mencoba mencocokkan komponen secara otomatis dengan fx: id dengan bidang yang ditentukan dalam pengontrol Anda dengan nama yang sama.

Misalkan kita memiliki tombol yang dijelaskan di atas dengan

 fx:id="mainButton" 

JavaFX mencoba menyuntikkan objek tombol ke controller Anda di bidang yang disebut mainButton :

 public class MainSceneController { //    fx:id = "mainButton" @FXML private Button mainButton; } 

Seperti dalam metode sebelumnya, bidang Anda harus publik atau @FXML beranotasi.

Sekarang kami memiliki tautan ke tombol kami, kami dapat dengan mudah mengubah teksnya:

 public class MainSceneController { @FXML private Button mainButton; @FXML private void buttonClicked() { mainButton.setText("Click me again!"); } } 

Pembuat adegan


Menulis struktur GUI Anda dalam XML mungkin lebih alami daripada di Jawa (terutama jika Anda terbiasa dengan HTML). Namun, itu masih sangat tidak nyaman. Berita baiknya adalah ada alat resmi yang disebut Scene Builder yang akan membantu Anda dalam menciptakan antarmuka pengguna. Singkatnya, ini adalah editor grafis untuk GUI Anda.



Editor memiliki tiga bidang utama:

  1. Bagian kiri menampilkan komponen yang tersedia yang dapat diseret ke bagian tengah. Ini juga berisi hierarki semua komponen di antarmuka pengguna Anda, sehingga Anda dapat dengan mudah menavigasi itu.
  2. Bagian tengah adalah aplikasi Anda yang ditampilkan berdasarkan file FXML Anda.
  3. Di sebelah kanan adalah inspektur komponen saat ini. Di sini Anda dapat mengedit berbagai properti komponen saat ini yang dipilih. Setiap komponen yang dipilih di tengah hierarki ditampilkan di inspektur.

Standalone


Scene Builder dapat diunduh sebagai aplikasi mandiri yang dapat digunakan untuk mengedit file FXML.

Integrasi dengan IntelliJ IDEA


Atau, Pembuat Pemandangan menawarkan integrasi dengan IDE.

Di IntelliJ IDEA, Anda dapat mengklik kanan pada file FXML apa pun dan kemudian memilih opsi Buka menu di SceneBuilder.

Atau, IntelliJ IDEA mengintegrasikan SceneBuilder langsung ke IDE. Jika Anda membuka file FXML di IDEA, dua tab akan muncul di bagian bawah layar

  • Teks
  • Pembuat skenario

Untuk setiap file FXML, Anda dapat dengan mudah beralih antara mengedit file FXML secara langsung atau melalui SceneBuilder.



Di IntelliJ IDEA, Anda dapat mengonfigurasi lokasi executable SceneBuilder:

Settings β†’ Languages & Frameworks β†’ JavaFX β†’ Path to SceneBuilder

Apa selanjutnya


Dalam posting berikutnya dalam seri kami, kami akan membahas beberapa tata letak dasar yang dapat digunakan untuk mengatur komponen aplikasi GUI di JavaFX.

Source: https://habr.com/ru/post/id474982/


All Articles