JavaFX Tutorial: styling CSS

Cara mendesain komponen JavaFX menggunakan CSS lama yang baik.

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

Pemisahan elemen visual


Dalam artikel sebelumnya tentang FXML, kami mempelajari bagaimana JavaFX memberikan pemisahan tugas yang jelas dengan membagi kode UI menjadi dua. Komponen dan propertinya dideklarasikan dalam file FXML, dan logika interaksi jelas dialokasikan ke controller.

Selain itu, ada bagian ketiga, bahasa FXML, yang hanya mengontrol komponen aplikasi Anda, sifat-sifatnya dan bagaimana mereka tertanam satu sama lain. Itu tidak mendefinisikan elemen visual dari suatu komponen, yaitu: font, warna, latar belakang, indentasi. Secara umum, Anda dapat mencapai ini di FXML, tetapi Anda seharusnya tidak melakukannya. Alih-alih, elemen visual harus didefinisikan secara jelas dalam style sheet CSS.

Dengan demikian, desain Anda menjadi independen dan dapat dengan mudah diganti atau diubah tanpa mempengaruhi sisa aplikasi. Anda bahkan dapat dengan mudah mengimplementasikan beberapa tema yang dapat diaktifkan sesuai permintaan pengguna.

CSS


Anda mungkin akrab dengan CSS (Cascading Style Sheets) yang digunakan untuk mendesain halaman HTML di web. Pendekatan serupa diterapkan di JavaFX, meskipun JavaFX menggunakan serangkaian properti khusus sendiri.

Mari kita lihat sebuah contoh:

.button { -fx-font-size: 15px; } 

Dua konsep utama digunakan di sini. Yang pertama adalah pemilih .tombol . Ini menentukan komponen yang gaya harus diterapkan. Dalam contoh ini, gaya diterapkan ke semua tombol.

Bagian kedua adalah sifat sebenarnya dari gaya, yang akan diterapkan ke semua komponen yang cocok dengan pemilih kami. Properti adalah segalanya di dalam kurung kurawal.

Setiap properti memiliki makna tertentu. Dalam contoh kita, ada properti -fx-font-size , yang menentukan seberapa besar teks tersebut. Dalam contoh, nilainya 15px , tetapi nilai ini bisa berupa yang lain.

Untuk meringkas - kami membuat aturan yang menyatakan bahwa semua tombol di mana saja harus memiliki teks 15 piksel.

Penyeleksi


Sekarang mari kita lihat lebih dekat bagaimana penyeleksi bekerja di JavaFX. Ini terjadi hampir sama dengan di CSS biasa.

Kelas


Kelas dalam CSS mewakili beberapa elemen serupa. Misalnya, tombol atau kotak centang. Selektor, yang harus diterapkan ke semua elemen dari kelas yang sama, dimulai dengan titik ".", Diikuti segera dengan nama kelas. Konvensi penamaan kelas adalah untuk memisahkan setiap kata dengan karakter "-". Pemilih berikut ini berlaku untuk semua elemen dengan kelas label .

 .label { // Some properties } 

Kelas bawaan


Berita baiknya adalah semua komponen bawaan JavaFX (seperti Label atau Tombol) sudah memiliki kelas yang telah ditentukan. Jika Anda ingin menyesuaikan gaya semua label dalam aplikasi Anda, Anda tidak perlu menambahkan kelas khusus untuk setiap label Anda. Setiap label memiliki kelas label secara default.

Sangat mudah untuk menentukan nama kelas dari komponen:

  • Ambil nama kelas komponen Java - misalnya. Label
  • Buat nama huruf kecil
  • Jika terdiri dari beberapa kata, pisahkan dengan simbol "-"

Beberapa contoh:

  • Label → Label
  • Kotak centang → kotak centang

Saat menggunakan kelas seperti penyeleksi, pastikan untuk menambahkan "." Ini berarti bahwa pemilih untuk kelas label adalah .label .

Kelas khusus


Jika kelas bawaan tidak cukup, Anda bisa menambahkan kelas Anda sendiri ke komponen Anda. Anda dapat menggunakan beberapa kelas yang dipisahkan oleh koma:

 <Label styleClass="my-label,other-class">I am a simple label</Label> 

Atau di Jawa:

 Label label = new Label("I am a simple label"); label.getStyleClass().addAll("my-label", "other-class"); 

Menambahkan kelas dengan cara ini tidak menghapus kelas komponen secara default (dalam hal ini, label ).

Ada satu kelas khusus yang disebut root . Ini adalah komponen root dari adegan Anda. Anda dapat menggunakannya untuk menata segala sesuatu di dalam adegan Anda (misalnya, mengatur font global). Ini mirip dengan menggunakan pemilih tag tubuh dalam HTML.

ID


Cara lain untuk memilih komponen dalam CSS adalah dengan menggunakan pengenal komponen (ID). Ini adalah pengidentifikasi unik untuk komponen. Tidak seperti kelas yang dapat ditugaskan ke beberapa komponen, pengidentifikasi harus unik di tempat kejadian.

Sedangkan simbol "." Digunakan untuk menunjukkan kelas. di depan nama di pemilihnya, pengidentifikasi ditandai dengan simbol "#".

 #my-component { ... } 

Di FXML, Anda dapat menggunakan fx: id untuk mengatur pengenal CSS suatu komponen.

 <Label fx:id="foo">I am a simple label</Label> 

Namun, ada satu peringatan. Identifier yang sama digunakan untuk merujuk ke objek komponen yang dideklarasikan di controller Anda dengan nama yang sama. Karena pengidentifikasi dan nama bidang dalam pengontrol harus cocok, fx: id harus memperhitungkan pembatasan penamaan Java untuk nama bidang. Meskipun konvensi penamaan CSS mendefinisikan kata individual yang dipisahkan oleh karakter "-", ini adalah karakter yang tidak valid untuk nama bidang Java. Karenanya, untuk fx: id dengan beberapa kata, Anda perlu menggunakan konvensi penamaan yang berbeda seperti CamelCase, atau menggunakan garis bawah.

 <!-- This is not valid --> <Label fx:id="my-label">I am a simple label</Label> <!-- This is valid --> <Label fx:id="my_label">I am a simple label</Label> <Label fx:id="MyLabel">I am a simple label</Label> 

Di Java, Anda bisa memanggil metode setId () dari komponen Anda.

 Label label = new Label("I am a simple label"); label.setId("foo"); 

Properti


Meskipun CSS yang digunakan dalam JavaFX sangat mirip dengan CSS web asli, ada satu perbedaan besar. Nama properti berbeda, dan ada banyak properti khusus JavaFX baru. Mereka memiliki awalan -fx- .

Berikut ini beberapa contohnya:

  • -fx-background-color : Warna latar belakang
  • -fx-text-fill : Warna teks
  • -fx-font-size : Ukuran teks

Anda dapat menemukan daftar semua properti di panduan desain resmi .

Kelas semu


Selain kelas yang biasa menandai komponen tertentu, ada yang disebut kelas semu yang menunjukkan keadaan komponen. Ini bisa berupa, misalnya, kelas untuk menandai bahwa komponen memiliki fokus atau kursor mouse ada di sana.

Ada banyak kelas pseudo bawaan. Mari kita lihat tombolnya. Ada beberapa pseudo-class yang dapat Anda gunakan, misalnya:

  • hover : tombol mouse di atas
  • terfokus : tombol memiliki fokus
  • dinonaktifkan : tombol dinonaktifkan
  • ditekan : tombol ditekan

Kelas pseudo dimulai dengan karakter ":" (misalnya :: hover ) di pemilih CSS. Tentu saja, Anda perlu menentukan komponen milik pseudo-class Anda - misalnya, tombol: hover . Contoh berikut menunjukkan pemilih yang berlaku untuk semua tombol yang memiliki fokus:

 .button:focused { -fx-background-color: red; } 

Tidak seperti CSS, yang hanya memiliki pseudo-class dasar untuk status seperti fokus dan melayang , JavaFX memiliki kelas pseudo-spesifik-komponen yang berhubungan dengan status atau properti komponen yang berbeda.

Sebagai contoh:

  • Scrollbar memiliki kelas pseudo horizontal dan vertikal
  • Elemen (Sel) memiliki kelas pseudo yang aneh dan genap
  • TitledPane telah memperluas dan menciutkan kelas semu.

Kelas Kustom Pseudo


Selain kelas pseudo bawaan, Anda dapat mendefinisikan dan menggunakan kelas pseudo Anda sendiri.

Mari kita buat label kita sendiri (mewarisi dari kelas Label). Ini akan memiliki properti logis baru yang disebut shiny . Dalam hal ini, kami ingin label kami memiliki pseudo- class yang mengkilap .

Karena tag memiliki pseudo- class mengkilap , kita dapat mengatur latar belakang tag emas :

 .shiny-label:shiny { -fx-background-color: gold; } 

Sekarang buat kelas itu sendiri.

 public class ShinyLabel extends Label { private BooleanProperty shiny; public ShinyLabel() { getStyleClass().add("shiny-label"); shiny = new SimpleBooleanProperty(false); shiny.addListener(e -> { pseudoClassStateChanged(PseudoClass.getPseudoClass("shiny"), shiny.get()); }); } public boolean isShiny() { return shiny.get(); } public void setShiny(boolean shiny) { this.shiny.set(shiny); } } 

Ada beberapa bagian penting di sini:

  1. Kami memiliki properti boolean BooleanProperty bukan boolean biasa. Ini berarti bahwa objek yang mengkilap dapat diamati, dan kita dapat melacak (mendengarkan) perubahan nilainya.
  2. Kami mendaftarkan pendengar yang akan dipanggil setiap kali nilai objek mengkilap berubah menggunakan shiny.addListener () .
  3. Ketika nilai shiny berubah, kita menambah / menghapus pseudo- class shiny tergantung pada nilai pseudoClassStateChanged saat ini (PseudoClass.getPseudoClass ("shiny"), shiny.get ()) .
  4. Kami menambahkan kelas khusus untuk semua label label mengkilap , alih-alih hanya memiliki kelas label yang diwarisi dari induknya. Dengan demikian, kami hanya dapat memilih tag mengkilap .

Lembar Gaya Default


Bahkan jika Anda sendiri tidak menyediakan gaya apa pun, setiap aplikasi JavaFX sudah memiliki beberapa gaya visual. Ada stylesheet default yang berlaku untuk setiap aplikasi. Ini disebut modena (sejak JavaFX 8, sebelumnya disebut caspian ).

Lembar gaya ini dapat ditemukan dalam file:

jfxrt.jar \ com \ sun \ javafx \ scene \ control \ skin \ modena \ modena.css

Atau Anda dapat menemukan file di sini . Dalam direktori yang sama ada banyak gambar yang digunakan oleh stylesheet.

Lembar gaya ini memberikan gaya standar, tetapi memiliki prioritas terendah dibandingkan jenis lembar gaya lainnya, sehingga Anda dapat dengan mudah menimpanya.

Lembar gaya adegan


Selain stylesheet default yang disebutkan di atas, Anda tentu saja dapat menyediakan sendiri. Level tertinggi di mana Anda dapat menerapkan gaya adalah seluruh adegan. Anda dapat menerapkan ini di FXML Anda:

 <BorderPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" stylesheets="styles.css" ... > ... </BorderPane> 

Atau dalam kode Java Anda:

 String stylesheet = getClass().getResource("/styles.css").toExternalForm(); scene.getStylesheets().add(stylesheet); 

Perhatikan panggilan keExternalForm () . Scene berharap mendapatkan konten stylesheet sebagai string, bukan file, jadi kami harus menyediakan konten stylesheet kami sebagai string.

Lembar gaya orang tua


Selain stylesheet untuk seluruh adegan, terkadang berguna untuk memiliki gaya di tingkat tata letak. Yaitu - untuk wadah terpisah, seperti VBox, HBox atau GridPane. Induk umum semua tata letak adalah kelas induk, yang mendefinisikan metode untuk memproses lembar gaya pada tingkat tata letak. Gaya ini hanya berlaku untuk komponen dalam tata letak ini, dan tidak untuk seluruh adegan. Gaya di tingkat tata letak lebih diutamakan daripada gaya di tingkat adegan.

 <HBox stylesheets="styles.css"> ... </HBox> 

Di Jawa, Anda perlu memuat konten stylesheet sendiri, seperti sebelumnya untuk adegan:

 HBox box = new HBox(); String stylesheet = getClass().getResource("/styles.css").toExternalForm(); box.getStylesheets().add(stylesheet); 

Gaya sebaris


Sejauh ini, kami hanya melihat kasus-kasus di mana style sheet eksternal telah ditetapkan untuk seluruh adegan atau tata letak. Tetapi Anda dapat mengatur properti gaya individu di tingkat komponen.

Di sini Anda tidak perlu khawatir tentang pemilih, karena semua properti diatur untuk komponen tertentu.

Anda dapat menentukan beberapa properti yang dipisahkan oleh titik koma:

 <Label style="-fx-background-color: blue; -fx-text-fill: white"> I'm feeling blue. </Label> 

Di Jawa, Anda bisa menggunakan metode setStyle () :

 Label label = new Label("I'm feeling blue."); label.setStyle("-fx-background-color: blue; -fx-text-fill: white"); 

Gaya pada tingkat komponen lebih diutamakan daripada gaya pemandangan serta gaya induk di tingkat tata letak.

Mengapa Anda harus menghindarinya?


Penataan tingkat komponen bisa nyaman, tetapi ini adalah solusi cepat dan kotor. Anda mengabaikan keunggulan utama CSS, yaitu pemisahan gaya dari komponen. Sekarang Anda secara kaku mengikat elemen visual Anda langsung ke komponen. Anda tidak lagi dapat dengan mudah mengganti lembar gaya jika diperlukan, Anda tidak dapat mengubah tema.

Selain itu, Anda tidak lagi memiliki satu tempat pusat di mana gaya Anda ditentukan. Ketika Anda perlu mengubah sesuatu dalam satu set komponen yang serupa, Anda perlu mengubah masing-masing komponen secara terpisah, dan tidak hanya mengedit satu tempat di style sheet eksternal. Oleh karena itu, gaya komponen inline harus dihindari.

Prioritas stylesheet


Anda dapat memberikan gaya pada beberapa level - scene, parent, style inline, dan ada juga stylesheet modem default. Jika Anda mengubah properti yang sama dari komponen yang sama di beberapa level, JavaFX memiliki pengaturan prioritas yang menentukan gaya mana yang harus digunakan. Daftar prioritas - dari yang tertinggi ke yang terendah:

  1. Gaya sebaris
  2. Gaya induk
  3. Gaya adegan
  4. Gaya bawaan

Ini berarti bahwa jika Anda mengatur warna latar belakang label tertentu pada level inline dan scene, JavaFX akan menggunakan nilai yang ditetapkan dalam gaya inline karena memiliki prioritas yang lebih tinggi.

Bacaan tambahan


JavaFX memiliki banyak properti CSS, dan uraiannya berada di luar cakupan posting ini, untuk daftar terperinci, lihat panduan referensi CSS resmi untuk JavaFX .

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


All Articles