Phương pháp đề xuất
Câu trả lời này liệt kê các cơ chế khác nhau để truyền tham số cho bộ điều khiển FXML.
Đối với các ứng dụng nhỏ, tôi đặc biệt khuyên bạn nên truyền tham số trực tiếp từ người gọi đến bộ điều khiển - đơn giản, dễ hiểu và không yêu cầu thêm khung.
Đối với các ứng dụng lớn hơn, phức tạp hơn, sẽ rất đáng để điều tra nếu bạn muốn sử dụng các cơ chế Dependency Injection hoặc Event Bus trong ứng dụng của mình.
Truyền tham số trực tiếp từ người gọi đến bộ điều khiển
Truyền dữ liệu tùy chỉnh cho bộ điều khiển FXML bằng cách truy xuất bộ điều khiển từ phiên bản trình tải FXML và gọi một phương thức trên bộ điều khiển để khởi tạo nó với các giá trị dữ liệu cần thiết.
Một cái gì đó giống như đoạn mã sau:
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer);
stage.show();
return stage;
}
...
class CustomerDialogController {
@FXML private Label customerName;
void initialize() {}
void initData(Customer customer) {
customerName.setText(customer.getName());
}
}
Một FXMLLoader mới được xây dựng như thể hiện trong mã mẫu tức là new FXMLLoader(location)
. Vị trí là một URL và bạn có thể tạo một URL như vậy từ tài nguyên FXML bằng cách:
new FXMLLoader(getClass().getResource("sample.fxml"));
Cẩn thận KHÔNG sử dụng chức năng tải tĩnh trên FXMLLoader, nếu không bạn sẽ không thể lấy bộ điều khiển từ phiên bản trình tải của mình.
Bản thân FXMLLoader không bao giờ biết bất cứ điều gì về các đối tượng miền. Bạn không trực tiếp chuyển các đối tượng miền cụ thể của ứng dụng vào hàm tạo FXMLLoader, thay vào đó bạn:
- Xây dựng một FXMLLoader dựa trên đánh dấu fxml tại một vị trí được chỉ định
- Nhận bộ điều khiển từ phiên bản FXMLLoader.
- Gọi các phương thức trên bộ điều khiển được truy xuất để cung cấp cho bộ điều khiển các tham chiếu đến các đối tượng miền.
Blog này (bởi một nhà văn khác) cung cấp một ví dụ thay thế, nhưng tương tự .
Đặt Bộ điều khiển trên FXMLLoader
CustomerDialogController dialogController =
new CustomerDialogController(param1, param2);
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
loader.setController(dialogController);
Pane mainPane = (Pane) loader.load();
Bạn có thể xây dựng một bộ điều khiển mới trong mã, chuyển bất kỳ tham số nào bạn muốn từ trình gọi của bạn vào hàm tạo của bộ điều khiển. Khi bạn đã xây dựng bộ điều khiển, bạn có thể đặt nó trên một cá thể FXMLLoader trước khi bạn gọi phương thức load()
cá thể .
Để đặt bộ điều khiển trên trình tải (trong JavaFX 2.x), bạn cũng không thể xác định một fx:controller
thuộc tính trong tệp fxml của mình.
Do giới hạn về fx:controller
định nghĩa trong FXML, cá nhân tôi thích nhận bộ điều khiển từ FXMLLoader hơn là đặt bộ điều khiển vào FXMLLoader.
Có bộ điều khiển lấy tham số từ phương thức tĩnh bên ngoài
Phương pháp này được minh họa bằng câu trả lời của Sergey cho Javafx 2.0 How-to Application.getParameter () trong một tệp Controller.java .
Sử dụng tiêm phụ thuộc
FXMLLoader hỗ trợ các hệ thống tiêm phụ thuộc như Guice, Spring hoặc Java EE CDI bằng cách cho phép bạn đặt nhà máy điều khiển tùy chỉnh trên FXMLLoader. Điều này cung cấp một cuộc gọi lại mà bạn có thể sử dụng để tạo phiên bản điều khiển với các giá trị phụ thuộc được chèn bởi hệ thống tiêm phụ thuộc tương ứng.
Một ví dụ về ứng dụng JavaFX và phép tiêm phụ thuộc bộ điều khiển với Spring được cung cấp trong câu trả lời cho:
Một cách tiếp cận tiêm phụ thuộc thực sự tốt đẹp, sạch sẽ được minh họa bằng khung afterburner.fx với một ứng dụng hack không khí mẫu sử dụng nó. afterburner.fx dựa vào JEE6 javax.inject để thực hiện tiêm phụ thuộc.
Sử dụng xe buýt sự kiện
Greg Brown, người tạo và triển khai đặc tả FXML ban đầu, thường đề nghị xem xét sử dụng xe buýt sự kiện, chẳng hạn như Guava EventBus , để liên lạc giữa các bộ điều khiển khởi tạo FXML và logic ứng dụng khác.
EventBus là một API xuất bản / đăng ký đơn giản nhưng mạnh mẽ với các chú thích cho phép các POJO giao tiếp với nhau ở bất cứ đâu trong JVM mà không cần phải tham khảo lẫn nhau.
Hỏi đáp tiếp theo
về phương pháp đầu tiên, tại sao bạn trở lại Giai đoạn? Phương thức cũng có thể bị vô hiệu vì bạn đã đưa ra lệnh show (); ngay trước khi trở lại sân khấu; Làm thế nào để bạn lập kế hoạch sử dụng bằng cách trở lại Giai đoạn
Đây là một giải pháp chức năng cho một vấn đề. Một giai đoạn được trả về từ showCustomerDialog
hàm để tham chiếu đến nó có thể được lưu trữ bởi một lớp bên ngoài có thể muốn làm gì đó, chẳng hạn như ẩn giai đoạn dựa trên một lần bấm nút trong cửa sổ chính, sau đó. Một giải pháp thay thế, hướng đối tượng có thể gói gọn chức năng và tham chiếu giai đoạn bên trong đối tượng CustomerDialog hoặc có Giai đoạn mở rộng CustomerDialog. Một ví dụ đầy đủ cho giao diện hướng đối tượng cho hộp thoại tùy chỉnh đóng gói dữ liệu FXML, bộ điều khiển và mô hình nằm ngoài phạm vi của câu trả lời này, nhưng có thể tạo một bài đăng blog đáng giá cho bất kỳ ai có xu hướng tạo một.
Thông tin bổ sung được cung cấp bởi người dùng StackOverflow có tên @dzim
Ví dụ cho Spring Boot Dependency Injection
Câu hỏi về cách thực hiện "Cách khởi động mùa xuân", đã có một cuộc thảo luận về JavaFX 2, mà tôi đã trả lời trong permalink đính kèm. Cách tiếp cận vẫn còn hiệu lực và được thử nghiệm vào tháng 3 năm 2016, trên Spring Boot v1.3.3.RELEASE:
https://stackoverflow.com/a/36310391/1281217
Đôi khi, bạn có thể muốn chuyển kết quả lại cho người gọi, trong trường hợp đó bạn có thể kiểm tra câu trả lời cho câu hỏi liên quan: