Перейти к основному содержимому

Справочник по JavaFX и Swing — элементы UI


Назначение

Пошаговые рецепты для JavaFX (OpenJFX) и Swing. Каркас — Первая программа на JavaFX, теория — 311.md. Имена элементов — Архитектура десктопных приложений; EDT и фоновые задачи — 112.md.


Как пользоваться (JavaFX)

  1. В start(Stage stage) создайте корневой контейнер (VBox, GridPane или BorderPane).
  2. Скопируйте рецепт элемента и добавьте узел в контейнер: box.getChildren().add(node) или grid.add(node, col, row).
  3. Прикрепите сцену: stage.setScene(new Scene(root, w, h)); stage.show();

UI меняют только в JavaFX Application Thread; из фона — Platform.runLater(() -> { ... }).


JavaFX

Главное окно (Stage + Scene)

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class App extends Application {
@Override
public void start(Stage stage) {
VBox root = new VBox(8);
stage.setTitle("Моё приложение");
stage.setScene(new Scene(root, 640, 480));
stage.setMinWidth(400);
stage.show();
}
public static void main(String[] args) { launch(args); }
}

Контейнер (VBox / GridPane / BorderPane)

import javafx.geometry.Insets;
import javafx.scene.layout.*;

VBox box = new VBox(10);
box.setPadding(new Insets(16));
box.getChildren().addAll(label, field, button);

GridPane grid = new GridPane();
grid.setHgap(8);
grid.setVgap(8);
grid.add(label, 0, 0);
grid.add(field, 1, 0);

BorderPane root = new BorderPane();
root.setTop(toolBar);
root.setCenter(table);
root.setBottom(statusLabel);

Label (метка)

import javafx.scene.control.Label;

Label label = new Label("Имя пользователя:");
label.setStyle("-fx-font-weight: bold;");

Label dynamic = new Label();
dynamic.setText("Готово");
// или label.textProperty().bind(otherProperty);
box.getChildren().add(label);

TextBox — однострочный (TextField)

import javafx.scene.control.TextField;

TextField field = new TextField();
field.setPromptText("Введите имя");
field.setPrefColumnCount(24);
String value = field.getText().trim();
field.clear();
field.setText("по умолчанию");

field.setOnAction(e -> submit()); // Enter
grid.add(field, 1, 0);

TextBox — многострочный (TextArea)

import javafx.scene.control.TextArea;

TextArea area = new TextArea();
area.setPrefRowCount(6);
area.setWrapText(true);
String text = area.getText();
area.clear();
grid.add(area, 0, 1, 2, 1);

Поле пароля (PasswordField)

import javafx.scene.control.PasswordField;

PasswordField pwd = new PasswordField();
String password = pwd.getText();
grid.add(pwd, 1, 2);

Button (кнопка)

import javafx.scene.control.Button;

Button save = new Button("Сохранить");
save.setOnAction(e -> onSave());
save.setDefaultButton(true); // Enter в форме
save.setCancelButton(false);
box.getChildren().add(save);

CheckBox (флажок)

import javafx.scene.control.CheckBox;

CheckBox notify = new CheckBox("Уведомления");
notify.setSelected(true);
notify.selectedProperty().addListener((obs, oldVal, selected) -> { /* ... */ });
boolean on = notify.isSelected();

RadioButton (переключатель)

import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;

ToggleGroup roles = new ToggleGroup();
RadioButton user = new RadioButton("Пользователь");
RadioButton admin = new RadioButton("Админ");
user.setToggleGroup(roles);
admin.setToggleGroup(roles);
user.setSelected(true);
String role = ((RadioButton) roles.getSelectedToggle()).getText();

ComboBox (выпадающий список)

import javafx.scene.control.ComboBox;
import javafx.collections.FXCollections;

ComboBox<String> combo = new ComboBox<>(FXCollections.observableArrayList("Работа", "Личное"));
combo.getSelectionModel().selectFirst();
combo.setEditable(false);
String choice = combo.getValue();
box.getChildren().add(combo);

ListView (список)

import javafx.scene.control.ListView;
import javafx.collections.FXCollections;

ListView<String> list = new ListView<>(FXCollections.observableArrayList("A", "B", "C"));
list.getSelectionModel().selectedItemProperty().addListener((obs, o, item) -> {
if (item != null) System.out.println(item);
});
list.getItems().add("D");
VBox.setVgrow(list, Priority.ALWAYS);

DataGrid (TableView)

import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.collections.FXCollections;

public class Person {
private final String name;
private final int age;
public Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
}

TableView<Person> table = new TableView<>();
TableColumn<Person, String> colName = new TableColumn<>("Имя");
colName.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn<Person, Number> colAge = new TableColumn<>("Возраст");
colAge.setCellValueFactory(new PropertyValueFactory<>("age"));
table.getColumns().addAll(colName, colAge);
table.setItems(FXCollections.observableArrayList(new Person("Алиса", 30)));
VBox.setVgrow(table, Priority.ALWAYS);

ProgressBar (индикатор прогресса)

import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;

ProgressBar bar = new ProgressBar(0.0); // 0.0 .. 1.0
bar.setProgress(0.5);

ProgressIndicator spin = new ProgressIndicator(-1); // неопределённый
box.getChildren().addAll(bar, spin);

Slider (ползунок)

import javafx.scene.control.Slider;

Slider slider = new Slider(0, 100, 50);
slider.setShowTickLabels(true);
slider.valueProperty().addListener((obs, o, v) -> label.setText(String.valueOf(v.intValue())));
double v = slider.getValue();

Поле поиска (фильтр)

TextField search = new TextField();
search.setPromptText("Поиск…");
search.textProperty().addListener((obs, old, query) -> {
list.getItems().setAll(allItems.stream()
.filter(s -> s.toLowerCase().contains(query.toLowerCase()))
.toList());
});

Вкладки (TabPane)

import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;

TabPane tabs = new TabPane();
Tab general = new Tab("Общее", new Label("Содержимое"));
Tab settings = new Tab("Настройки");
settings.setContent(new VBox(new CheckBox("Опция")));
general.setClosable(false);
tabs.getTabs().addAll(general, settings);
BorderPane.setMargin(tabs, new Insets(8));
root.setCenter(tabs);

import javafx.scene.control.*;

MenuBar menuBar = new MenuBar();
Menu file = new Menu("Файл");
MenuItem open = new MenuItem("Открыть");
open.setOnAction(e -> openFile());
file.getItems().addAll(open, new SeparatorMenuItem(), new MenuItem("Выход"));
menuBar.getMenus().add(file);
root.setTop(menuBar);

ToolBar (панель инструментов)

import javafx.scene.control.ToolBar;

ToolBar toolBar = new ToolBar(
new Button("Новый"),
new Separator(),
new Button("Сохранить")
);
toolBar.getItems().forEach(node -> {
if (node instanceof Button b) b.setOnAction(e -> { /* ... */ });
});
root.setTop(toolBar);

StatusBar (строка состояния)

Label status = new Label("Готово");
status.setMaxWidth(Double.MAX_VALUE);
status.setStyle("-fx-padding: 4 8; -fx-background-color: #eee;");
HBox.setHgrow(status, Priority.ALWAYS);
HBox statusBar = new HBox(status);
root.setBottom(statusBar);
status.setText("Сохранено");

ScrollPane (прокрутка)

import javafx.scene.control.ScrollPane;

VBox content = new VBox(/* много виджетов */);
ScrollPane scroll = new ScrollPane(content);
scroll.setFitToWidth(true);
VBox.setVgrow(scroll, Priority.ALWAYS);
box.getChildren().add(scroll);

Диалоги и FileChooser

import javafx.scene.control.Alert;
import javafx.stage.FileChooser;

new Alert(Alert.AlertType.INFORMATION, "Готово").showAndWait();

Alert confirm = new Alert(Alert.AlertType.CONFIRMATION, "Удалить файл?");
confirm.showAndWait().filter(r -> r == ButtonType.OK).ifPresent(r -> delete());

FileChooser fc = new FileChooser();
fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("JSON", "*.json"));
File f = fc.showOpenDialog(stage);
File save = fc.showSaveDialog(stage);

Tooltip (подсказка)

import javafx.scene.control.Tooltip;

Button btn = new Button("?");
Tooltip.install(btn, new Tooltip("Сохранить на диск"));

Context menu (контекстное меню)

ContextMenu menu = new ContextMenu(
new MenuItem("Копировать"),
new MenuItem("Вставить")
);
list.setContextMenu(menu);
// или для произвольного узла:
node.setOnContextMenuRequested(e -> menu.show(node, e.getScreenX(), e.getScreenY()));

Дочернее окно (Stage)

Stage dialog = new Stage();
dialog.initOwner(primaryStage);
dialog.initModality(Modality.WINDOW_MODAL);
dialog.setScene(new Scene(new VBox(new Label("Настройки")), 320, 200));
dialog.showAndWait();

Swing

Каркас — 131.md — Swing. Все изменения UI — в EDT: SwingUtilities.invokeLater(() -> { ... }).

Главное окно (JFrame)

import javax.swing.*;

JFrame frame = new JFrame("Моё приложение");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640, 480);
frame.setLocationRelativeTo(null);
JPanel root = new JPanel(new BorderLayout(8, 8));
frame.add(root);
frame.setVisible(true);

Label — JLabel

JLabel label = new JLabel("Имя:");
root.add(label, BorderLayout.NORTH);
label.setText("Обновлено");

TextField — JTextField

JTextField field = new JTextField(20);
String v = field.getText();
field.setText("по умолчанию");
panel.add(field);

TextArea — JTextArea

JTextArea area = new JTextArea(8, 30);
area.setLineWrap(true);
panel.add(new JScrollPane(area));

Password — JPasswordField

JPasswordField pwd = new JPasswordField(16);
char[] pass = pwd.getPassword();

Button — JButton

JButton btn = new JButton("Сохранить");
btn.addActionListener(e -> save());
panel.add(btn);

CheckBox / RadioButton

JCheckBox chk = new JCheckBox("Включено", true);
JRadioButton a = new JRadioButton("A");
JRadioButton b = new JRadioButton("B");
ButtonGroup group = new ButtonGroup();
group.add(a);
group.add(b);

ComboBox — JComboBox

JComboBox<String> combo = new JComboBox<>(new String[]{"Работа", "Личное"});
String item = (String) combo.getSelectedItem();

List — JList

JList<String> list = new JList<>(new String[]{"A", "B", "C"});
list.addListSelectionListener(e -> {
if (!e.getValueIsAdjusting()) System.out.println(list.getSelectedValue());
});
panel.add(new JScrollPane(list));

Table — JTable

import javax.swing.table.DefaultTableModel;

String[] cols = {"Имя", "Возраст"};
Object[][] data = {{"Алиса", 30}};
JTable table = new JTable(new DefaultTableModel(data, cols));
panel.add(new JScrollPane(table));

ProgressBar — JProgressBar

JProgressBar bar = new JProgressBar(0, 100);
bar.setValue(50);
bar.setIndeterminate(true);

Tabs — JTabbedPane

JTabbedPane tabs = new JTabbedPane();
tabs.addTab("Общее", new JLabel("Контент"));
tabs.addTab("Настройки", new JPanel());
root.add(tabs, BorderLayout.CENTER);

JMenuBar bar = new JMenuBar();
JMenu file = new JMenu("Файл");
JMenuItem exit = new JMenuItem("Выход");
exit.addActionListener(e -> frame.dispose());
file.add(exit);
bar.add(file);
frame.setJMenuBar(bar);

ToolBar — JToolBar

JToolBar toolBar = new JToolBar();
toolBar.add(new JButton("Новый"));
toolBar.setFloatable(false);
root.add(toolBar, BorderLayout.NORTH);

StatusBar

JLabel status = new JLabel(" Готово");
status.setBorder(BorderFactory.createLoweredBevelBorder());
root.add(status, BorderLayout.SOUTH);

Диалоги

JOptionPane.showMessageDialog(frame, "Текст");
int ok = JOptionPane.showConfirmDialog(frame, "Удалить?");
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
}

Tooltip

btn.setToolTipText("Сохранить документ");

Context menu — JPopupMenu

JPopupMenu popup = new JPopupMenu();
popup.add(new JMenuItem("Копировать"));
list.setComponentPopupMenu(popup);

Частые ошибки

СимптомJavaFXSwing
UI не обновляется из потокаPlatform.runLaterSwingUtilities.invokeLater
Окно пустоеНет stage.show()Нет setVisible(true)
Module not foundOpenJFX в Maven

См. также


См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").