====== JavaFX ======
===== Сведения =====
:!: Сведения
**Stage** - окружающее окно, которое содержит в себе остальные элементы. Может быть несколько, но должно быть как минимум одно. Является основным контейнером и точкой входа\\
**Scene** - отображает содержание **stage**. **Stage** может содержать несколько scene, которые можно между собой переключать. Внутри реализуется графом объектов (**Scene Graph**), где каждый элемент является узлом (**node**)\\
**Node** - элемент управления, например кнопки, метки или даже макеты (**layout**), внутри которых может быть несколько вложенных компонентов. У каждого узла свой идентификатор, стиль и т.д.\\
===== Использование =====
Есть как минимум пару вариантов использования, которые несколько разнятся\\
:!: Интерфейс в fxml файлах
Простая форма fxml\\
(myApp/src/main/resources/maket/rootWindow.fxml)
Контроллер\\
(myApp/src/main/java/com/myApp/myApp/controller/BaseController.java)\\
package com.sakeeper.sakeeper.controller;
import com.sakeeper.sakeeper.Sakeeper;
import com.sakeeper.sakeeper.model.Product;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
public class BaseController {
private Sakeeper sakeeper;
@FXML
private Button product1;
@FXML
private Button product2;
public void setSakeeper(Sakeeper sakeeper){
this.sakeeper = sakeeper;
}
@FXML
private void product1(){
sakeeper.showVolumeWindow(new Product("product_1"));
}
@FXML
private void product2(){
sakeeper.showVolumeWindow(new Product("product_2"));
}
}
Основной код, главный файл
package com.sakeeper.sakeeper;
import com.sakeeper.sakeeper.controller.BaseController;
import com.sakeeper.sakeeper.controller.VolumeController;
import com.sakeeper.sakeeper.model.Product;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import java.io.IOException;
public class Sakeeper extends Application {
private Stage primaryStage;
private VBox rootLayout;
public Sakeeper(){
// list add's
}
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage primaryStage) throws IOException {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("saKeeper");
showBaseWindow();
}
// Это основное окно
public void showBaseWindow(){
try{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Sakeeper.class.getResource("/maket/rootWindow.fxml"));
rootLayout = loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
BaseController controller = loader.getController();
controller.setSakeeper(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
// Это уже второе окно, в примере его нет
public void showVolumeWindow(Product selectedProduct){
try{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Sakeeper.class.getResource("/maket/volumeWindow.fxml"));
VBox page = loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Выберите объем");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
dialogStage.setScene(new Scene(page));
VolumeController volumeController = loader.getController();
volumeController.setDialogStage(dialogStage);
volumeController.setProduct(selectedProduct);
dialogStage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
}
:!: Интерфейс в коде
Элементы так же могут создаваться в коде, размещаться на форме и задаваться свойства\\
public void showBaseWindow(){
try{
(..)
Button newButt = new Button("This dynamic button");
/*newButt.setOnAction(event -> {
Alert message = new Alert(Alert.AlertType.INFORMATION);
message.setContentText("this message from dynamic button ");
message.show();
});*/
/*EventHandler rightClickHandler = event -> {
if (MouseButton.SECONDARY.equals(event.getButton())) {
button.setFont(new Font(button.getFont().getSize() + 1));
}
};*/
//Create the EventHandler
EventHandler hnd = new EventHandler() {
@Override
//handle method
public void handle(ActionEvent ev) {
Alert message = new Alert(Alert.AlertType.INFORMATION);
message.setContentText("this message from dynamic button ");
message.show();
}
};
newButt.setOnAction(hnd);
rootLayout.getChildren().add(newButt);
(...)
} catch (IOException e) {
e.printStackTrace();
}
}
===== Оформление =====
Хорошее разделение должно придерживаться пути:\\
* логика в java (модели/контроллеры)
* элементы формы в FXML описании
* а оформление в CSS
В JavaFX не совсем тот самый общеизвестный CSS, имеет собственные свойства\\
Выбор компонентов либо селектором (название типа компонента, с точкой вначале, либо ИД с решеткой вначале) аналогично CSS\\
:!: Примеры
.button {
-fx-font-size: 15px;
}
.label {
// Some properties
}
#my-component {
...
}
# или в java
Label label = new Label("I am a simple label");
label.getStyleClass().addAll("my-label", "other-class");
#
Label label = new Label("I am a simple label");
label.setId("foo");
Подключение
...
#
String stylesheet = getClass().getResource("/styles.css").toExternalForm();
scene.getStylesheets().add(stylesheet);
#
...
#
HBox box = new HBox();
String stylesheet = getClass().getResource("/styles.css").toExternalForm();
box.getStylesheets().add(stylesheet);