Application, Stage и Scene
Любое приложение JavaFX — это класс-наследник Application. JavaFX сам создаёт его объект, вызывает нужные методы в нужном порядке и передаёт в start готовое главное окно. Понимать этот порядок нужно, чтобы знать, где строить интерфейс, а где — освобождать ресурсы.
Жизненный цикл
| Метод | Когда вызывается | Что в нём делают |
|---|---|---|
init() | До создания окна | Читают настройки; интерфейс здесь создавать нельзя |
start(Stage) | Когда всё готово | Строят сцену и показывают окно |
stop() | После закрытия последнего окна | Сохраняют данные, закрывают соединения |
Обязателен только start, остальные методы по умолчанию пустые. Метод launch в main запускает всю эту цепочку.
Пример с тремя методами
Добавим в App все три метода и выведем, в каком потоке работает каждый:
// src/main/java/com/example/notes/App.java
package com.example.notes;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void init() {
System.out.println("init: " + Thread.currentThread().getName());
}
@Override
public void start(Stage stage) {
System.out.println("start: " + Thread.currentThread().getName());
Label label = new Label("Здесь будут заметки");
StackPane root = new StackPane(label);
Scene scene = new Scene(root, 640, 480);
stage.setTitle("Заметки");
stage.setMinWidth(400);
stage.setMinHeight(300);
stage.setScene(scene);
stage.show();
}
@Override
public void stop() {
System.out.println("stop: приложение закрывается");
}
public static void main(String[] args) {
launch(args);
}
}После mvn javafx:run откроется окно с надписью «Здесь будут заметки» по центру. Уменьшить его меньше 400 × 300 не получится. Когда закроете окно, в терминале будет:
init: JavaFX-Launcher
start: JavaFX Application Thread
stop: приложение закрываетсяПоток JavaFX
start, stop и все обработчики нажатий выполняются в одном потоке — JavaFX Application Thread. Только в нём можно создавать окна и менять интерфейс. Метод init работает в другом потоке, поэтому окна в нём не создают. Как выполнять долгую работу, не замораживая окно, — в уроке о фоновых задачах.
Stage, Scene и корень
Окно Stage показывает одну сцену. Сцене при создании передают корневой узел и размер:
// src/main/java/com/example/notes/App.java — фрагмент start()
StackPane root = new StackPane(label);
Scene scene = new Scene(root, 640, 480);
stage.setScene(scene);StackPane — простейший контейнер: он кладёт узлы друг на друга и выравнивает по центру. Сцену можно заменить на другую в любой момент — так переключают экраны.
Полезные методы окна:
| Метод | Что делает |
|---|---|
setTitle(String) | Задаёт заголовок окна |
setMinWidth(double), setMinHeight(double) | Ограничивают минимальный размер |
setResizable(boolean) | Запрещает или разрешает менять размер |
show() | Показывает окно |
close() | Закрывает окно |
Частая ошибка
Окно пытаются создать в main до вызова launch, например new Stage(). JavaFX ещё не запущен, и программа падает с java.lang.IllegalStateException: Not on FX application thread; currentThread = main. Весь код интерфейса пишите в start или в методах, которые из него вызываются.