วันหนึ่ง ฉันมีความคิดที่จะเขียนแอปพลิเคชันเดสก์ท็อปขนาดเล็กตามความต้องการของฉัน เช่น พจนานุกรมขนาดเล็กสำหรับการเรียนรู้คำศัพท์ภาษาต่างประเทศ และฉันก็เริ่มสับสน ฉันจะทำเช่นนี้ได้อย่างไร แน่นอนว่าสิ่งแรกที่เข้ามาในใจฉันคือสวิง ทุกคนคงเคยได้ยินชื่อสวิง นี่คือไลบรารีสำหรับสร้างส่วนต่อประสานกราฟิกกับผู้ใช้ เนื่องจาก Oracle อันเป็นที่รักของเรายังไม่ได้ละทิ้ง Swing โดยสิ้นเชิงจึงไม่ถือว่าล้าสมัยและแอปพลิเคชันยังคงทำงานอยู่ อย่างไรก็ตาม Swing ไม่ได้รับการปรับปรุงให้ทันสมัยอีกต่อไป และเจ้าหน้าที่ของ Oracle ได้ทำให้เราได้สัมผัสถึงอนาคตของ JavaFX และในความเป็นจริง JavaFX ใช้ส่วนประกอบ Swing เป็นผู้ให้บริการ)
มาดูโค้ดกันสักหน่อย เนื่องจากฉันใช้ Java 8 ฉันจึงไม่จำเป็นต้องดึงการขึ้นต่อกันใดๆ เนื่องจาก JavaFx อยู่ใน JDK ตามค่าเริ่มต้น (เช่นเดียวกับใน Java 9.10) แต่ถ้าเรามี Java 11+ เราก็ต้องไปที่ maven repository และ ดึงมันออกมาจากการพึ่งพาที่นั่น
8 - สร้างไฟล์เป็นวัตถุรูปภาพ ซึ่งเชื่อมต่อกับไฟล์จริงโดยสตรีมที่ส่งผ่านในตัวสร้าง 9 - ตั้งค่าไอคอนที่แผงด้านบนของหน้าต่าง 11 - สร้างวัตถุปุ่ม 13-16 - ตั้งค่าปฏิกิริยาเมื่อกดปุ่ม 17 - สร้างฉากที่ เราวางปุ่ม 18 - วางฉากบนหน้าต่างทั่วไปของเรา 20 - ตั้งค่าสถานะการมองเห็นสำหรับหน้าต่าง และด้วยเหตุนี้เราจึงได้หน้าต่างเล็ก ๆ ไว้ต้อนรับ Pesels ที่เราชื่นชอบ:
ทุกอย่างดูง่ายกว่า Swing มากใช่ไหม แต่มันยังไม่จบ การเขียนโค้ดทั้งหมดเพื่อแสดงแอปพลิเคชันนั้นไม่ดี คุณต้องแบ่งส่วนเพื่อให้เข้าใจได้ง่ายขึ้น (องค์ประกอบกราฟิกในตะกร้าหนึ่ง ตรรกะในอีกตะกร้าหนึ่ง) และที่นี่ xml เข้ามาในรูปภาพ... โอ้พระเจ้า xml? อย่างแน่นอน. โดยเฉพาะอย่างยิ่ง เราใช้การใช้งานเฉพาะสำหรับ JavaFX - FXML ซึ่งเรากำหนดส่วนประกอบกราฟิกของแอปพลิเคชันและคุณสมบัติ (ทุกขนาด ฯลฯ) จากนั้นเชื่อมต่อกับคอนโทรลเลอร์ ซึ่งช่วยจัดการตรรกะ ลองดูตัวอย่าง xml นี้:
(เหมือนหน้าต่างสำหรับขึ้นทะเบียนสุนัข)
เมื่อคุณเลือกสุนัขและกดปุ่ม Delete สุนัขนั้นจะถูกลบออกจากรายการของเรา เมื่อคุณเลือกเพื่อนสี่ขาและเปลี่ยนฟิลด์ และหลังจากกดปุ่มแก้ไข ข้อมูลของสุนัขก็จะถูกอัปเดต เมื่อเรากดปุ่ม New จะมีหน้าต่างปรากฏขึ้นมาเพื่อสร้างบันทึกสำหรับสุนัขตัวใหม่ (เริ่มต้นด้วยชื่อ):
จากนั้นคลิกบันทึกและกรอกข้อมูลในฟิลด์ที่เหลือในหน้าต่างแรก จากนั้นคลิกปุ่มแก้ไขเพื่อ บันทึก. ฟังดูง่ายใช่มั้ย? มาดูกันว่าสิ่งนี้จะมีลักษณะอย่างไรในแอปพลิเคชัน Java ของเรา ขั้นแรก ฉันจะทิ้งเค้าโครง xml ไว้ที่นี่สำหรับสองหน้าต่างที่สร้างขึ้นใน
อย่างที่คุณเห็น ไม่มีอะไรพิเศษ มีตัวควบคุมที่แสดงถึงหน้าต่างบางบาน มีแบบจำลองที่แสดงถึงข้อมูลของเรา มาดูคลาสที่เปิดตัวแอปพลิเคชันกัน (Application Implementation):
นั่นคือทั้งหมดที่ฉันมีสำหรับวันนี้ วันนี้เราได้ทำความคุ้นเคยกับแนวคิดพื้นฐานและตัวอย่างการใช้ JavaFX สั้น ๆ และเราสามารถสร้างแอปพลิเคชันเดสก์ท็อปขนาดเล็กได้ (โดยใช้ข้อมูลเพิ่มเติม ซึ่งโชคดีที่มีอยู่มากมายบนอินเทอร์เน็ต) และคุณก็ชอบ))
JavaFX คืออะไร?
JavaFX นั้นเป็นชุดเครื่องมือ GUI สำหรับ Java จะมีการพูดนอกเรื่องเล็กน้อยที่นี่ และเราจะจำได้ว่าGUI คืออะไร : ส่วนติดต่อผู้ใช้แบบกราฟิก - ส่วนติดต่อผู้ใช้แบบกราฟิกคือประเภทของส่วนติดต่อผู้ใช้ที่องค์ประกอบทั้งหมด (ปุ่ม เมนู ไอคอน รายการ) นำเสนอต่อผู้ใช้บน การแสดงผลจะทำในรูปแบบรูปภาพ กราฟิก ไม่เหมือนกับอินเทอร์เฟซบรรทัดคำสั่ง ใน GUI ผู้ใช้สามารถเข้าถึงออบเจ็กต์ที่มองเห็นได้โดยสุ่มโดยใช้อุปกรณ์อินพุต บ่อยครั้งที่องค์ประกอบอินเทอร์เฟซถูกนำมาใช้ในรูปแบบของคำอุปมาอุปมัยและแสดงคุณสมบัติและวัตถุประสงค์เพื่ออำนวยความสะดวกในการทำความเข้าใจผู้ใช้ JavaFXมีวัตถุประสงค์เพื่อสร้างเกมและแอปพลิเคชันเดสก์ท็อปใน Java ในความเป็นจริงมันจะมาแทนที่ Swing เนื่องจากเครื่องมือ GUI ใหม่สำหรับ Java ที่เสนอ นอกจากนี้ยังช่วยให้เราจัดสไตล์ไฟล์เลย์เอาต์ GUI (XML) และทำให้ดูหรูหรายิ่งขึ้นโดยใช้ CSS คล้ายกับสิ่งที่เราคุ้นเคยในเว็บแอปพลิเคชัน JavaFX ยังจัดการกราฟิก 3D ในตัวรวมถึงแอปพลิเคชันเสียง วิดีโอ และเครือข่ายแบบฝังในชุดเครื่องมือ GUI เดียว... เรียนรู้ได้ง่ายและได้รับการปรับให้เหมาะสมอย่างเหมาะสม รองรับระบบปฏิบัติการหลายระบบ เช่นเดียวกับระบบ Windows, UNIX และ Mac OS
คุณสมบัติ JavaFX:
- ในตอนแรก JavaFX มาพร้อมกับชุดส่วนอินเทอร์เฟซแบบกราฟิกจำนวนมาก เช่น ปุ่มทุกประเภท ช่องข้อความ ตาราง ต้นไม้ เมนู แผนภูมิ ฯลฯ ซึ่งจะช่วยประหยัดเวลาได้มาก
- JavaFX มักใช้สไตล์ CSS และเราจะสามารถใช้รูปแบบ FXML พิเศษเพื่อสร้าง GUI แทนที่จะทำในโค้ด Java ทำให้ง่ายต่อการจัดวาง GUI หรือเปลี่ยนรูปลักษณ์หรือองค์ประกอบอย่างรวดเร็วโดยไม่ต้องเล่นกับโค้ด Java เป็นเวลานาน
- JavaFX มีส่วนไดอะแกรมที่พร้อมใช้งาน ดังนั้นเราจึงไม่จำเป็นต้องเขียนมันตั้งแต่ต้นทุกครั้งที่คุณต้องการไดอะแกรมพื้นฐาน
- JavaFX ยังมาพร้อมกับการรองรับกราฟิก 3D ซึ่งมักจะมีประโยชน์หากเรากำลังพัฒนาเกมบางประเภทหรือแอปพลิเคชันที่คล้ายกัน
- โดยพื้นฐานแล้ว Stageคือหน้าต่างโดยรอบที่ทำหน้าที่เป็นผืนผ้าใบเริ่มต้นและประกอบด้วยส่วนประกอบที่เหลือ แอปพลิเคชันสามารถมีได้หลายขั้นตอน แต่ไม่ว่าในกรณีใด จะต้องมีองค์ประกอบดังกล่าวเพียงองค์ประกอบเดียว โดยพื้นฐานแล้ว Stage คือคอนเทนเนอร์หลักและจุดเริ่มต้น
- ฉาก - แสดงเนื้อหาของเวที (เหมือนตุ๊กตาทำรัง) แต่ละด่านสามารถมีองค์ประกอบได้หลายอย่าง - ฉากซึ่งสามารถสลับกันได้ ภายใน สิ่งนี้ถูกนำไปใช้โดยกราฟวัตถุที่เรียกว่ากราฟฉาก (โดยที่แต่ละองค์ประกอบเป็นโหนดหรือที่เรียกว่าโหนด )
- โหนดคือตัวควบคุม เช่น ปุ่มป้ายกำกับ หรือแม้แต่เค้าโครง ซึ่งสามารถมีส่วนประกอบที่ซ้อนกันหลายรายการอยู่ภายในได้ แต่ละฉากสามารถมีโหนดที่ซ้อนกันได้เพียงโหนดเดียว แต่อาจเป็นเลย์เอาต์ที่มีองค์ประกอบหลายส่วนได้ การซ้อนสามารถมีได้หลายระดับ โดยมีเลย์เอาต์ที่ประกอบด้วยเลย์เอาต์อื่นและส่วนประกอบทั่วไป แต่ละโหนดดังกล่าวมีตัวระบุ สไตล์ เอฟเฟกต์ สถานะ และตัวจัดการเหตุการณ์ของตัวเอง

JavaFX: ตัวอย่างการใช้งาน
เราสร้างชั้นเรียนปกติด้วยวิธีการmain
(จุดเริ่มต้น):
public class AppFX extends Application {
public static void main(String[] args) {
Application.launch();
}
@Override
public void start(Stage primaryStage) throws Exception {
pimarySatge.show();
}
}
ที่นี่ชั้นเรียนของเราสืบทอดมาจากjavafx.application.Application
(ซึ่งเราได้รับจากกล่อง Bugaga) โดยหลักแล้ว เราเรียกวิธีแอปพลิเคชันแบบคงที่launch()
เพื่อเปิดหน้าต่างของเรา นอกจากนี้ ความคิดของเราจะบ่นว่าเราไม่ได้ใช้วิธีการสมัครstart
ซึ่งเป็นสิ่งที่เราทำในท้ายที่สุด มีไว้เพื่ออะไร? และเพื่อให้สามารถจัดการคุณสมบัติได้ (การทำงานของหน้าต่างของเรา) ในการทำเช่น นี้เราใช้อาร์กิวเมนต์ขาเข้าprimaryStage
ซึ่งเราเรียกเมธอดshow
เพื่อให้เราเห็นว่าหน้าต่างถูกเปิดขึ้นมา main
มากรอกวิธีการของเรากันสักหน่อยstart
:
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Dogs application");
primaryStage.setWidth(500);
primaryStage.setHeight(400);
InputStream iconStream =
getClass().getResourceAsStream("/images/someImage.png");
Image image = new Image(iconStream);
primaryStage.getIcons().add(image);
Button button = new Button("WOF WOF ???'");
button.setOnAction(e -< {
Alert alert = new Alert(Alert.AlertType.INFORMATION, "WOF WOF WOF!!!");
alert.showAndWait();
});
Scene primaryScene = new Scene(button);
primaryStage.setScene(primaryScene);
primaryStage.show();
}
แล้วเราเห็นอะไรที่นี่? มาดูทีละบรรทัด: 2 - ตั้งชื่อหน้าต่างเอง (ระยะ) 3.4 - กำหนดขนาด 6.7 - กำหนดเส้นทางของสตรีมการอ่านไปยังไฟล์ (ไอคอน) 

<?xml version="1.0" encoding="UTF-8"?>
<?language javascript?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
id="Dogs application" prefHeight="200" prefWidth="300" alignment="center">
<Label text="Wow wow?"/>
<Button fx:id="mainButton" text="Greeting" onAction="buttonClicked()"/>
<fx:script>
function buttonClicked() {
mainButton.setText("Wow wow wow!!!")
}
</fx:script>
</VBox>
2 - ภาษาสคริปต์ที่เราใช้ 4-6 - ข้อมูลที่นำเข้า 8-9 Vbox - คอนเทนเนอร์ที่วางส่วนประกอบย่อยไว้ในบรรทัดเดียว 11 - แสดงข้อความ 13 - ปุ่มเมื่อคลิกเราใช้วิธีที่อธิบายไว้ในสคริปต์ในบรรทัดที่ 15-18 ควรมีรหัสสำหรับการเรียกไฟล์ xml นี้ในวิธีการstart
แต่ตอนนี้สิ่งนี้ไม่สำคัญนักและเรา จะละไว้ (ด้านล่างจะมีตัวอย่างการดึงไฟล์นี้) แน่นอนว่า xml นั้นดี (แต่ไม่ดีมาก) การเขียนด้วยตนเองนั้นน่าสับสนมาก นี่ไม่ใช่ศตวรรษที่แล้วใช่ไหม 
ขอแนะนำ JavaFX SceneBuilder
เมื่อมาถึงจุดนี้เองที่ (กลองม้วน) เข้ามามีบทบาท -SceneBuilder
ใน JavaFX Scene Builderเป็นเครื่องมือที่เราสามารถออกแบบหน้าต่างของเราในรูปแบบของอินเทอร์เฟซแบบกราฟิกแล้วบันทึกหน้าต่างเหล่านั้น และโปรแกรมนี้ตามผลลัพธ์จะ สร้างไฟล์ xml ที่เราเราจะปรับปรุงในแอปพลิเคชันของเรา อินเทอร์เฟซของตัวสร้าง fmxl นี้มีลักษณะดังนี้: 
การพูดนอกเรื่องเล็กน้อย บทเรียน JavaFX
ฉันจะข้ามรายละเอียดการติดตั้งและการศึกษาโดยละเอียดของเครื่องมือนี้ด้วย เหล่านี้เป็นหัวข้อที่ควรค่าแก่การสำรวจเพิ่มเติม ดังนั้น ฉันยังคงทิ้งลิงก์ที่น่าสนใจสองสามลิงก์ไปยังบทเรียน JavaFX: หนึ่ง (บทช่วยสอนออนไลน์บน JavaFX) และสองลิงก์ (บทช่วยสอนที่ดีอีกบทหนึ่ง) มาดูตัวอย่างเล็กๆ น้อยๆ ที่ฉันร่างไว้กันดีกว่า ในที่สุดฉันก็ได้สิ่งที่ชอบ:

SceneBuilder
: อันดับแรก (พื้นฐาน):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<AnchorPane prefHeight="300.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.tutorial.controller.BaseController">
<children>
<SplitPane dividerPositions="0.29797979797979796" prefHeight="300.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TableView fx:id="dogs" layoutX="-2.0" layoutY="-4.0" prefHeight="307.0" prefWidth="190.0" AnchorPane.bottomAnchor="-5.0" AnchorPane.leftAnchor="-2.0" AnchorPane.rightAnchor="-13.0" AnchorPane.topAnchor="-4.0">
<columns>
<TableColumn fx:id="nameList" prefWidth="100.33334350585938" text="Nickname" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Label layoutX="49.0" layoutY="25.0" text="Person Details" AnchorPane.leftAnchor="5.0" AnchorPane.topAnchor="5.0" />
<GridPane accessibleText="erreererer" gridLinesVisible="true" layoutX="5.0" layoutY="31.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="31.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="17.0" prefWidth="70.0" text="Nickname" />
<Label text="Breed" GridPane.rowIndex="1" />
<Label text="Age" GridPane.rowIndex="2" />
<Label text="City" GridPane.rowIndex="3" />
<Label text="Level of training" GridPane.rowIndex="4" />
<TextField fx:id="breed" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="age" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextField fx:id="city" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextField fx:id="levelOfTraining" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<TextField fx:id="name" GridPane.columnIndex="1" />
</children>
</GridPane>
<Button layoutX="251.0" layoutY="259.0" mnemonicParsing="false" onAction="#create" text="New" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="230.0" AnchorPane.rightAnchor="130.0" AnchorPane.topAnchor="260.0" />
<Button layoutX="316.0" layoutY="262.0" mnemonicParsing="false" onAction="#edit" text="Edit" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="290.0" AnchorPane.rightAnchor="70.0" AnchorPane.topAnchor="260.0" />
<Button layoutX="360.0" layoutY="262.0" mnemonicParsing="false" onAction="#delete" text="Delete" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="350.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="260.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
ประการที่สอง (เพื่อสร้างสุนัขใหม่):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="200.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.tutorial.controller.NewDogController">
<children>
<GridPane layoutX="31.0" layoutY="25.0" prefHeight="122.0" prefWidth="412.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="185.0" minWidth="10.0" prefWidth="149.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="173.0" minWidth="10.0" prefWidth="146.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="48.0" prefWidth="178.0" text="Please, write name:">
<font>
<Font size="20.0" />
</font>
</Label>
<TextField fx:id="nickName" prefHeight="36.0" prefWidth="173.0" GridPane.columnIndex="1" />
</children>
</GridPane>
<Button layoutX="222.0" layoutY="149.0" mnemonicParsing="false" onAction="#ok" prefHeight="37.0" prefWidth="95.0" text="Save" />
<Button layoutX="325.0" layoutY="149.0" mnemonicParsing="false" onAction="#cansel" prefHeight="37.0" prefWidth="95.0" text="Cansel" />
</children>
</AnchorPane>
โครงสร้างโฟลเดอร์มีลักษณะอย่างไร: 
@Data
public class AppFX extends Application {
private Stage primaryStage;
private AnchorPane rootLayout;
private ObservableList listDog = FXCollections.observableArrayList();
public AppFX() {
listDog.add(new Dog("Fluffy", "Pug", 8, "Odessa", 2));
listDog.add(new Dog("Archie", "Poodle", 3, "Lviv", 6));
listDog.add(new Dog("Willie", "Bulldog", 5, "Kiev", 4));
listDog.add(new Dog("Hector", "Shepherd", 9, "Minsk", 6));
listDog.add(new Dog("Duncan", "Dachshund", 1, "Hogwarts", 9));
}
ที่นี่เราเห็นตัวสร้างที่จะกรอกข้อมูลเริ่มต้นของเรา (ซึ่งเราจัดเก็บไว้ในแผ่นงานพิเศษ - ObservableList)
public static void main(String[] args) {
Application.launch();
}
@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Dogs application");
showBaseWindow();
}
ไม่มีอะไรพิเศษ - main
และการใช้งานstart()
ที่เปิดตัวแอปพลิเคชัน:
public void showBaseWindow() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(AppFX.class.getResource("/maket/rootWindow.fxml"));
rootLayout = loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
InputStream iconStream = getClass().getResourceAsStream("/icons/someImage.png");
Image image = new Image(iconStream);
primaryStage.getIcons().add(image);
BaseController controller = loader.getController();
controller.setAppFX(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
ดังนั้นที่นี่เราจะเห็นวิธีการที่เราเปิดตัวจริงstart()
กล่าวคือวิธีที่กำหนดการตั้งค่าของหน้าต่างฐานของเรา เช่นในรูปแบบ xml ในทรัพยากร: ให้ไอคอน ลิงก์ไปยังคอนโทรลเลอร์เฉพาะ และให้ลิงก์ไปยังthis
คลาสกับคอนโทรลเลอร์)
public void showCreateWindow(Dog dog) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(AppFX.class.getResource("/maket/new.fxml"));
AnchorPane page = loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Wow Wow Wow");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
dialogStage.setScene(new Scene(page));
CreateController controller = loader.getController();
controller.setDialogStage(dialogStage);
controller.setDog(dog);
dialogStage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ที่นี่เราจะเห็นวิธีการที่รับผิดชอบในการปรากฏของหน้าต่างที่สอง - หน้าต่างสำหรับสร้างบันทึกใหม่ (ชื่อของสุนัขตัวใหม่) นอกจากนี้เรายังตั้งค่าคอนโทรลเลอร์, เค้าโครง xml, สเตจ ฯลฯ ... คลาสถัดไปที่เราจะพิจารณาจะเป็นโมเดลที่แสดงถึงสุนัขของเรา (ข้อมูลเกี่ยวกับมัน): @Data
public class Dog {
private StringProperty name;
private StringProperty breed;
private IntegerProperty age;
private StringProperty city;
private IntegerProperty levelOfTraining;
public Dog(String name, String breed, int age, String city, int levelOfTraining) {
this.name = new SimpleStringProperty(name);
this.breed = new SimpleStringProperty(breed);
this.age = new SimpleIntegerProperty(age);
this.city = new SimpleStringProperty(city);
this.levelOfTraining = new SimpleIntegerProperty(levelOfTraining);
}
public Dog() {
name = new SimpleStringProperty();
breed = null;
age = null;
city = null;
levelOfTraining = null;
}
}
ที่นี่เราเห็น Constructor สองตัว ตัวหนึ่งเกือบจะเป็นตัวปกติที่มีอาร์กิวเมนต์ทั้งหมด (เกือบเพราะเราใช้ FX wrapper พิเศษประเภทธรรมดา) และตัวสร้างที่ไม่มีอาร์กิวเมนต์: เราใช้มันเมื่อสร้าง dog ตัวใหม่ ซึ่งในตอนแรกมีเพียง ชื่อ. ตัวควบคุมสำหรับหน้าต่างพื้นฐาน: @Data
public class BaseController {
@FXML
private TableView dogs;
@FXML
private TableColumn nameList;
@FXML
private TextField name;
@FXML
private TextField breed;
@FXML
private TextField age;
@FXML
private TextField city;
@FXML
private TextField levelOfTraining;
private AppFX appFX;
ที่นี่เราเห็นเขตข้อมูลวัตถุของเรา แต่อยู่ในรูปแบบ TextField นี่คือรูปแบบที่แสดงช่องป้อนข้อความ @FXML เป็นคำอธิบายประกอบที่ออกแบบมาเพื่อเชื่อมโยงโค้ด Java และออบเจ็กต์ที่เกี่ยวข้องของเลย์เอาต์ของเรา (ปุ่ม ฟิลด์ หรืออย่างอื่น)
@FXML
private void initialize() {
nameList.setCellValueFactory(
cellData -> cellData.getValue().getName());
dogs.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> showDogsInformation(newValue));
}
ที่นี่เราเห็นวิธีการแสดงชื่อสุนัข ทางด้านขวาของรายการ (คำอธิบายประกอบ @FXML เชื่อมโยงกับส่วนประกอบเค้าโครง JavaFX TableView)
public void setAppFX(AppFX appFX) {
this.appFX = appFX;
dogs.setItems(appFX.getListDog());
}
private void showDogsInformation(Dog dog) {
if (dog != null) {
name.setText(dog.getName() != null ? dog.getName().getValue() : null);
breed.setText(dog.getBreed() != null ? dog.getBreed().getValue() : null);
age.setText(dog.getAge() != null ? String.valueOf(dog.getAge().get()) : null);
city.setText(dog.getCity() != null ? dog.getCity().getValue() : null);
levelOfTraining.setText(dog.getLevelOfTraining() != null ? String.valueOf(dog.getLevelOfTraining().get()) : null);
} else {
name.setText("");
breed.setText("");
age.setText("");
city.setText("");
levelOfTraining.setText("");
}
}
ในวิธีแรก เราจะเห็นการตั้งค่าการอ้างอิงภายในไปยังคลาสที่ใช้ Application (เพื่อให้เราสามารถเรียกวิธีการเรียกหน้าต่างที่สองได้) และการตั้งค่ารายการเริ่มต้นที่จะแสดง ประการที่สองตรวจสอบว่าสุนัขปัจจุบันมีข้อมูลบางอย่างหรือไม่ และโดยอิงจากการตั้งค่านี้ ฟิลด์ข้อความ:
@FXML
private void delete() {
int selectedIndex = dogs.getSelectionModel().getSelectedIndex();
dogs.getItems().remove(selectedIndex);
}
@FXML
private void edit() {
int selectedIndex = dogs.getSelectionModel().getSelectedIndex();
dogs.getItems().set(selectedIndex, new Dog(name.getText(), breed.getText(), Integer.valueOf(age.getText()), city.getText(), Integer.valueOf(levelOfTraining.getText())));
}
@FXML
private void create() {
Dog someDog = new Dog();
appFX.showCreateWindow(someDog);
if (someDog.getName() != null && !someDog.getName().getValue().isEmpty()) {
appFX.getListDog().add(someDog);
}
}
}
ที่นี่เราจะเห็นสามวิธีของหน้าต่างฐานที่เกี่ยวข้องกับปุ่ม: 
- ลบ — ลบสุนัขที่เลือก (เลือก) ตามดัชนี;
- แก้ไข - สร้างสุนัขตัวใหม่ด้วยข้อมูลที่ถ่ายโอนและตั้งค่าแทนอันที่เคยเป็นมาก่อน
- สร้าง - เราสร้างสุนัขตัวใหม่และเรียกวิธีการเรียกหน้าต่างการสร้างส่งวัตถุใหม่และหลังจากปิดซึ่งหากชื่อไม่เป็นโมฆะให้บันทึกสัตว์เลี้ยงตัวใหม่
@Data
public class CreateController {
private Stage dialogStage;
private Dog dog;
@FXML
private TextField nickName;
@FXML
private void ok() {
if (nickName != null && !nickName.getText().isEmpty()) {
dog.setName(new SimpleStringProperty(nickName.getText()));
dialogStage.close();
}
}
@FXML
private void cansel() {
dialogStage.close();
}
}
ที่นี่เราเห็นการเชื่อมต่อกับช่องข้อความในหน้าต่างโดยประมวลผลปุ่มบันทึกและยกเลิกซึ่งจะปิดหน้าต่าง อย่างที่คุณเห็น เพื่อความสะดวกยิ่งขึ้นในแอปพลิเคชันขนาดเล็กของฉัน ฉันใช้ลอมบอก ไม่เช่นนั้นโค้ดจะเติบโตขึ้นอย่างมาก และฉันก็คงไม่เหมาะกับการรีวิวของฉัน
GO TO FULL VERSION