идея
Воспользуйтесь преимуществами декларативного шаблона проектирования JavafX / FXML и разрешите пользователям настраивать определенное представление без какого-либо кодирования, просто открывая его, например, с помощью SceneBuilder, чтобы переупорядочить макет или добавить новые элементы управления или даже изменить стиль в соответствии с потребностями пользователей.
Файл FXML + CSS могут быть размещены в любом месте, где они доступны через URL. Пользователь должен знать только интерфейс / методы назначенного класса контроллера внутри FXML.
Пульт дистанционного управления
Предполагая, что этот простой класс демонстрационного контроллера предоставляет методы для удаленного управления устройствами и отправки сообщений MQTT, пользователь может настроить свое собственное дистанционное управление.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class RemoteController{ @FXML public void onTest(){ Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setContentText( "" ); alert.setHeaderText( "WORKS!" ); alert.show(); } public void onTest(String value){ Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText( "WORKS!" ); alert.setContentText(value); alert.show(); } public void onSwitch(String houseCode, int groudId, int deviceId, String command){ Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText( "Switch!" ); alert.setContentText(String.format( "Command: send %s %d %d %s" , houseCode, groudId, deviceId, command)); alert.show(); } } |
remote.fxml и remote.css
Обратите внимание на ссылки de.jensd.shichimifx.demo.ext.RemoteController
и remote.css
.
Таким образом, в основном действия контроллера могут быть вызваны через:
1
|
onAction= "#onTest" . |
Ницца:
Если вы добавите:
1
|
<?language javascript?> |
в FXML также возможно передавать параметры посредством вызова JavaScript через экземпляр controller
.
1
2
|
onAction=controller.onTest( 'OFF' ) onAction=controller.onSwitch( 'a' , 1 , 1 , 'ON' ) |
К сожалению, я не могу найти больше документации об этой функции, чем -> это , но каким-то образом это волшебным образом работает 😉 Можно даже передавать различные типы параметров.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<? xml version = "1.0" encoding = "UTF-8" ?> <? language javascript?> <? import javafx.geometry.*?> <? import java.lang.*?> <? import java.net.*?> <? import java.util.*?> <? import javafx.scene.*?> <? import javafx.scene.control.*?> <? import javafx.scene.layout.*?> < VBox alignment = "TOP_CENTER" prefHeight = "400.0" prefWidth = "600.0" spacing = "20.0" styleClass = "main-pane" stylesheets = "@remote.css" xmlns = "http://javafx.com/javafx/8" xmlns:fx = "http://javafx.com/fxml/1" fx:controller = "de.jensd.shichimifx.demo.ext.RemoteController" > < children > < Label styleClass = "title-label" text = "Universal Remote" /> < HBox alignment = "CENTER_RIGHT" spacing = "20.0" > < children > < Label layoutX = "228.0" layoutY = "96.0" styleClass = "sub-title-label" text = "Light Frontdoor" /> < Button layoutX = "43.0" layoutY = "86.0" mnemonicParsing = "false" onAction = "#onTest" prefWidth = "150.0" styleClass = "button-on" text = "ON" /> < Button layoutX = "411.0" layoutY = "86.0" mnemonicParsing = "false" onAction = "#onTest" prefWidth = "150.0" styleClass = "button-off" text = "OFF" /> </ children > < padding > < Insets left = "10.0" right = "10.0" /> </ padding > </ HBox > < HBox alignment = "CENTER_RIGHT" spacing = "20.0" > < children > < Label layoutX = "228.0" layoutY = "96.0" styleClass = "sub-title-label" text = "Light Garden" /> < Button layoutX = "43.0" layoutY = "86.0" mnemonicParsing = "false" onAction = "controller.onTest('ON')" prefWidth = "150.0" styleClass = "button-on" text = "ON" /> < Button layoutX = "411.0" layoutY = "86.0" mnemonicParsing = "false" onAction = "controller.onTest('OFF')" prefWidth = "150.0" styleClass = "button-off" text = "OFF" /> </ children > < padding > < Insets left = "10.0" right = "10.0" /> </ padding > </ HBox > < HBox alignment = "CENTER_RIGHT" spacing = "20.0" > < children > < Label layoutX = "228.0" layoutY = "96.0" styleClass = "sub-title-label" text = "Light Garden" /> < Button layoutX = "43.0" layoutY = "86.0" mnemonicParsing = "false" onAction = "controller.onSwitch('a', 1,1,'ON')" prefWidth = "150.0" styleClass = "button-on" text = "ON" /> < Button layoutX = "411.0" layoutY = "86.0" mnemonicParsing = "false" onAction = "controller.onTest('OFF')" prefWidth = "150.0" styleClass = "button-off" text = "OFF" /> </ children > < padding > < Insets left = "10.0" right = "10.0" /> </ padding > </ HBox > </ children > < padding > < Insets bottom = "20.0" left = "20.0" right = "20.0" top = "20.0" /> </ padding > </ VBox > |
На основе этого примера пользователь может просто открыть FXMl с помощью SceneBuilder и добавить новую кнопку, вызывающую метод controller.onSwitch () для управления различными / новыми устройствами, установленными для домашней автоматизации.
FxmlUtils
Следующая версия ShichimiFX будет содержать новый класс Utilily для загрузки FXML, как показано в ExternalFXMLDemoController
. Обратите внимание, что загруженная панель добавляется в центр externalPane
(BorderPane) демонстрационного приложения через onLoadExternalFxml()
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
public class ExternalFXMLDemoController { @FXML private ResourceBundle resources; @FXML private BorderPane externalPane; @FXML private TextField fxmlFileNameTextField; @FXML private Button chooseFxmlFileButton; @FXML private Button loadFxmlFileButton; private StringProperty fxmlFileName; public void initialize() { fxmlFileNameTextField.textProperty().bindBidirectional(fxmlFileNameProperty()); loadFxmlFileButton.disableProperty().bind(fxmlFileNameProperty().isEmpty()); } public StringProperty fxmlFileNameProperty() { if (fxmlFileName == null ) { fxmlFileName = new SimpleStringProperty( "" ); } return fxmlFileName; } public String getFxmlFileName() { return fxmlFileNameProperty().getValue(); } public void setFxmlFileName(String fxmlFileName) { this .fxmlFileNameProperty().setValue(fxmlFileName); } @FXML public void chooseFxmlFile() { FileChooser chooser = new FileChooser(); chooser.setTitle( "Choose FXML file to load" ); if (getFxmlFileName().isEmpty()) { chooser.setInitialDirectory( new File(System.getProperty( "user.home" ))); } else { chooser.setInitialDirectory( new File(getFxmlFileName()).getParentFile()); } File file = chooser.showOpenDialog(chooseFxmlFileButton.getScene().getWindow()); if (file != null ) { setFxmlFileName(file.getAbsolutePath()); } } @FXML public void onLoadExternalFxml() { try { Optional<URL> url = FxmlUtils.getFxmlUrl(Paths.get(getFxmlFileName())); if (url.isPresent()) { Pane pane = FxmlUtils.loadFxmlPane(url.get(), resources); externalPane.setCenter(pane); } else { Alert alert = new Alert(Alert.AlertType.WARNING); alert.setContentText(getFxmlFileName() + " could not be found!" ); alert.show(); } } catch (IOException ex) { Dialogs.create().showException(ex); } } } |
Ссылка: | Как разрешить пользователям настраивать пользовательский интерфейс от нашего партнера JCG Йенса Детерса в блоге JavaFX Delight . |