Java Swing — окна и кнопки
Приветствую! Здесь вы наверняка найдете, что ищете. Примеры в лаборатории рассчитаны на то, что мы разбираем что-то конкретное.
Текущая статья посвящена примерам: Swing на Java с построчным разбором.
Поэтому за теорией по текущей теме вам — в энциклопедию. Если ещё не погружались, то маршрут прост:
- Основы
- Система и сеть
- Данные и разметка
- Код и разработка
- Языки
- Искусственный интеллект
- Проект
- Инфраструктура и безопасность
- Спин-офф
Обязательно пройдитесь.
А теперь приступим к нашему предмету.
Обзор GUI — JavaFX и GUI (там же сравнение со Swing).
Рецепты по элементам — справочник JavaFX и Swing.
Короткие примеры в энциклопедии — Простые приложения.
Аналог на Python — Tkinter — окна и виджеты.
Мобильный UI — Flutter — готовые виджеты.
Поток UI и «зависание» окна — особенности десктопа.
Подборка готовых программ на Java Swing с построчным разбором — «что написано» и «зачем так».
Навигация по примерам
| Раздел | Тема |
|---|---|
| Каркас Swing | java swing tutorial, jframe example, SwingUtilities invokeLater |
| Окно с меткой | jlabel example java, java gui hello world |
| Кнопка и диалог | jbutton click listener java, joptionpane showmessagedialog |
| Поле ввода | jtextfield get text, java gui input dialog |
| Конвертер °C | java temperature converter gui, jtextfield parse double |
| Чекбоксы и радио | jcheckbox jradiobutton example, ButtonGroup java |
| Список задач | jlist add element, DefaultListModel java |
| Ползунок | jslider example, ChangeListener java swing |
| Форма входа | gridlayout jpanel, jpasswordfield example |
| Меню | jmenubar example, jmenuitem actionlistener |
| Калькулятор | java calculator swing, gridbaglayout example |
| Популярные запросы | java gui calculator, swing login form, jframe set size |
| Частые ошибки | jvm not exiting, swing ui thread, could not find main class |
Из чего состоит окно на Swing
Любая учебная программа с GUI строится из трёх слоёв:
- Окно —
JFrame(рамка, заголовок, кнопка закрытия). - Контейнер —
JPanelс менеджером компоновки (FlowLayout,BorderLayout,GridLayout…). - Виджеты —
JLabel,JButton,JTextFieldи остальные элементы.
JFrame «Моё приложение»
└── ContentPane (по умолчанию BorderLayout)
├── NORTH → JToolBar (кнопки «Новый», «Сохранить»)
├── CENTER → JPanel + поля ввода
└── SOUTH → JLabel «Готово» (строка состояния)
| Консольная программа | Swing-приложение |
|---|---|
Scanner читает из терминала |
JTextField.getText() читает из поля |
System.out.println |
JLabel.setText или JOptionPane |
| Программа ждёт Enter в консоли | Программа ждёт клик или событие в окне |
Завершение после main |
Окно живёт, пока пользователь не закроет крестик |
| Консоль Java | Swing | Tkinter (Python) | |
|---|---|---|---|
| Библиотека | в JDK | в JDK (javax.swing) |
в CPython |
| Главное окно | нет | JFrame |
tk.Tk() |
| Цикл событий | нет | EDT (поток Swing) | mainloop() |
| Кнопка | нет | JButton + ActionListener |
Button + command= |
Поток EDT — почему окно «живёт» само
Swing рисует интерфейс в Event Dispatch Thread (EDT). Все создание и изменение кнопок, надписей, размеров окна должны происходить в этом потоке.
flowchart LR
A[javac + java] --> B[main]
B --> C[SwingUtilities.invokeLater]
C --> D[Создать JFrame и виджеты]
D --> E[setVisible true]
E --> F{Событие в EDT?}
F -->|Клик JButton| G[ActionListener]
F -->|Крестик| H[EXIT_ON_CLOSE]
G --> F
Пока окно открыто, метод main уже завершился, но процесс Java не заканчивается — работает EDT. Если в обработчике кнопки считать факториал миллиона секунд, окно замрёт — для долгих задач нужен SwingWorker (Особенности разработки десктопных приложений).
Обязательный каркас Swing
Любой пример ниже повторяет этот шаблон.
Разбор построчно:
| Строка | Смысл |
|---|---|
import javax.swing.* |
Пакет Swing: JFrame, JButton, JLabel, JOptionPane… Звёздочка импортирует часто используемые классы. |
public class AppFrame |
Имя класса = имя файла AppFrame.java. |
public static void main |
Точка входа JVM — как в консоли. |
SwingUtilities.invokeLater(() -> { .. }) |
Запланировать создание UI в EDT. Без этого на части ОС IDE предупреждает о небезопасном доступе к Swing. |
() -> { .. } |
Лямбда — короткая анонимная функция без имени; тело в фигурных скобках. |
new JFrame("Моё приложение") |
Главное окно; строка в заголовке окна. |
setDefaultCloseOperation(EXIT_ON_CLOSE) |
Крестик завершает JVM. Без этого окно исчезнет, а процесс java может остаться в диспетчере задач. |
setSize(400, 300) |
Ширина и высота клиентской области в пикселях. |
setLocationRelativeTo(null) |
Центр экрана. null значит «относительно всего дисплея». |
setVisible(true) |
Показать окно. До этого пользователь ничего не увидит. |
Компиляция и запуск:
javac AppFrame.java
java AppFrame
| Симптом | Причина |
|---|---|
Could not find or load main class |
Запускаете не из той папки или имя класса в java не совпадает с файлом |
| Окно мелькнуло | Нет invokeLater + сразу конец main без EXIT_ON_CLOSE и видимого окна |
javac is not recognized |
JDK не установлен или не в PATH |
Стартовые окна
Простые программы «с нуля» — с них. У каждого блока: файл, код, таблица строк, что увидите на экране.
Минимальное окно с меткой
Запрос: java swing hello world, jlabel center.
Задача: доказать, что JDK и Swing работают — одно окно с текстом.
Файл: HelloLabel.java
Разбор построчно:
| Строка | Смысл |
|---|---|
JLabel label = new JLabel(..) |
Виджет только для текста — пользователь в него не печатает. |
"Окно работает!" |
Строка на экране. |
SwingConstants.CENTER |
Выравнивание текста по центру области метки. |
frame.add(label) |
JFrame по умолчанию использует BorderLayout — add без зоны кладёт виджет в CENTER (центр окна). |
Что увидите: окно ~320×160, по центру надпись «Окно работает!».
Частая ошибка: ожидать, что JLabel сам «появится» без frame.add — виджет должен быть добавлен в контейнер.
Что попробовать: label.setFont(label.getFontderiveFont(18f)) перед frame.add — крупнее шрифт.
Кнопка и диалог JOptionPane
Запрос: jbutton actionlistener lambda, joptionpane example.
Задача: по клику показать всплывающее сообщение — основа калькулятора, форм, меню.
Файл: HelloButton.java
Разбор построчно:
| Строка | Смысл |
|---|---|
JButton btn = new JButton("Нажми меня") |
Кнопка с подписью на лицевой стороне. |
addActionListener(e -> ..) |
Подписка на событие «нажали». e — объект события (ActionEvent), здесь не используется. |
e -> JOptionPane.. |
Лямбда: при клике выполнить тело один раз. |
JOptionPane.showMessageDialog(frame, ..) |
Модальное окно поверх frame; пока не нажали OK, фокус не уйдёт. |
INFORMATION_MESSAGE |
Иконка «i» в диалоге (стиль зависит от ОС). |
Сравнение с Tkinter: там command=on_click без скобок. В Java в addActionListener передают функцию e -> .., а не результат вызова.
Что попробовать: JOptionPane.showConfirmDialog — возвращает YES_OPTION / NO_OPTION, можно ветвить if.
Поле ввода и приветствие
Запрос: jtextfield example, java gui get user input.
Задача: прочитать имя из поля, проверить пустоту, показать диалог.
Файл: HelloForm.java
Разбор построчно:
| Строка | Смысл |
|---|---|
JPanel panel = new JPanel(new GridLayout(2, 2, 8, 8)) |
Панель-контейнер; сетка 2 строки × 2 столбца, отступ между ячейками 8 px. |
BorderFactory.createEmptyBorder(16, 16, 16, 16) |
Внутренний отступ панели от края окна (верх, лево, низ, право). |
new JTextField(16) |
Однострочное поле; 16 — «примерная ширина в символах». |
getTexttrim() |
Взять строку из поля и убрать пробелы по краям. |
name.isEmpty() |
Проверка «пользователь ничего не ввёл». |
greetBtn.doClick() |
Программно «нажать» кнопку — срабатывает тот же ActionListener. |
nameField.addActionListener(e -> greetBtn.doClick()) |
Клавиша Enter в поле = тот же код, что у кнопки. |
frame.pack() |
Подогнать размер окна под содержимое после GridLayout. |
Что увидите: компактная форма; пустое имя → жёлтое предупреждение; иначе приветствие.
Что попробовать: второе поле «Фамилия» — расширьте GridLayout до 3 строк.
Конвертер °C → °F
Запрос: java gui temperature converter, parse double jtextfield.
Задача: классическая лабораторная — число, формула, результат в интерфейсе.
Файл: TempConverter.java
Разбор построчно:
| Строка | Смысл |
|---|---|
replace(',', '.') |
В русской локали часто печатают 25,5 — для parseDouble нужна точка. |
Double.parseDouble(raw) |
Строка → число; при буквах бросает NumberFormatException. |
celsius * 9 / 5 + 32 |
Формула Фаренгейта. |
resultLabel.setText(..) |
Обновить надпись без пересоздания виджета. |
Runnable convert = () -> { .. } |
Именованный блок логики; кнопка и Enter вызывают convert.run(). |
Вход / выход (пример):
| Ввод в поле | На экране в resultLabel |
|---|---|
0 |
0,0 °C = 32,0 °F |
100 |
100,0 °C = 212,0 °F |
abc |
Диалог «Введите число…» |
Что попробовать: кнопка «Очистить» — celsiusField.setText("") и resultLabel.setText("—").
Флажок и переключатели
Запрос: jcheckbox jradiobutton, ButtonGroup swing.
Файл: SettingsPanel.java
Разбор построчно:
| Строка | Смысл |
|---|---|
JCheckBox(.., true) |
Второй аргумент — начальное состояние «включено». |
JRadioButton + ButtonGroup |
В группе только одна кнопка может быть выбрана. |
isSelected() |
true, если галочка / радио активны. |
BoxLayout.Y_AXIS |
Виджеты столбиком сверху вниз. |
Box.createVerticalStrut(12) |
Пустой промежуток 12 px между блоками. |
updateStatus.run() при старте |
Сразу показать строку статуса, не ждать первого клика. |
Список задач (JList)
Запрос: jlist add item java, java todo list swing.
Файл: TodoList.java
Разбор построчно:
| Строка | Смысл |
|---|---|
DefaultListModel<String> |
Модель данных списка — сюда добавляют и удаляют строки. |
JList<>(model) |
Виджет отображает то, что в модели. |
model.addElement(text) |
Строка в конец списка. |
list.getSelectedIndex() |
Индекс выделенной строки или −1, если ничего не выбрано. |
model.remove(idx) |
Удалить по индексу. |
new JScrollPane(list) |
Полосы прокрутки, если задач больше, чем помещается. |
BorderLayout.NORTH / CENTER |
Поле сверху, список занимает остаток окна. |
Мини-проект для отчёта: этот файл + скриншот окна = готовая «программа учёта задач».
Ползунок громкости
Запрос: jslider changelistener, java swing slider example.
Файл: VolumeSlider.java
Разбор построчно:
| Строка | Смысл |
|---|---|
new JSlider(0, 100, 50) |
Минимум 0, максимум 100, старт 50. |
setMajorTickSpacing(25) |
Деления на шкале каждые 25 единиц. |
ChangeListener |
Срабатывает при каждом движении ползунка (не только по клику). |
getValueIsAdjusting() |
Пока пользователь тянет мышью — true; можно не обновлять текст на каждом пикселе. |
slider.getValue() |
Текущее число на шкале. |
Примеры окон и компонентов
Тематические блоки для курсовой: компоновка, текст, меню, диалоги, мини-приложения.
Форма входа (GridLayout + пароль)
Запрос: jpasswordfield example, java login form swing.
Файл: LoginGrid.java — см. код в справочнике 3112; ниже полная программа.
Разбор:
| Элемент | Смысл |
|---|---|
JPasswordField |
Символы скрыты точками; getPassword() возвращает char[], не String |
Пустая JLabel в сетке |
Заглушка, чтобы кнопка «Войти» встала во второй столбец третьей строки |
Меню и строка состояния
Запрос: jmenubar jmenuitem example.
Файл: MenuDemo.java
Разбор: setJMenuBar — полоса «Файл / Справка»; addSeparator() — линия между пунктами; BorderLayout.SOUTH — статус внизу, как в блокноте.
Простой калькулятор (+ и −)
Запрос: java swing calculator code, gridbaglayout example.
Файл: MiniCalc.java — два поля, кнопки «+» и «−», результат в JLabel.
Разбор: GridBagLayout — гибкая таблица (сложнее GridLayout, зато ячейки разного размера). calc.run("+") — одна функция на две кнопки.
Счётчик (кнопка меняет JLabel)
Классика из Простые приложения на Java — здесь с таблицей строк.
Файл: CounterApp.java
Разбор построчно:
| Строка | Смысл |
|---|---|
int[] counter = {0} |
Массив из одного элемента — обход правила «переменная в лямбде должна быть effectively final». |
counter[0]++ |
Увеличить значение при каждом клике. |
label.setText(..) |
Обновление UI в EDT — здесь это безопасно, обработчик кнопки уже в EDT. |
В курсовой чаще делают поле класса private int counter = 0; — тот же смысл, чище для ООП.
Типовые задачи
Короткие фрагменты, которые часто вставляют в готовую лабораторную.
Только JFrame по центру экрана
JFrame f = new JFrame("Заголовок");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
Текст кнопки и отключение кнопки
JButton b = new JButton("Старт");
b.setText("Стоп");
b.setEnabled(false);
Диалог «Да / Нет»
int ans = JOptionPane.showConfirmDialog(frame, "Удалить запись?", "Подтверждение", JOptionPane.YES_NO_OPTION);
if (ans == JOptionPane.YES_OPTION) { /* удалить */ }
Добавить элемент в JComboBox
JComboBox<String> combo = new JComboBox<>(new String[]{"A", "B"});
combo.addItem("C");
String x = (String) combo.getSelectedItem();
JTextArea с прокруткой
JTextArea area = new JTextArea(10, 30);
area.setLineWrap(true);
frame.add(new JScrollPane(area), BorderLayout.CENTER);
Частые ошибки новичка
| Симптом | Причина | Решение |
|---|---|---|
| Окно не появляется | Нет setVisible(true) |
Вызвать после add всех виджетов |
| JVM не завершается | Нет EXIT_ON_CLOSE |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) |
| Окно «зависло» | Долгий цикл в ActionListener |
Вынести в фон + SwingUtilities.invokeLater для UI |
| UI странный из другого потока | Обновление не в EDT | Обернуть в invokeLater |
Could not find main class |
Неверное имя при java X |
Имя класса = имя файла без .java |
| Пустое окно | Всё ушло в NORTH, CENTER пуст |
Проверить зоны BorderLayout |
| Кнопка «сработала» при старте | Вызвали метод вместо лямбды | addActionListener(e -> fn()), не addActionListener(fn()) если fn уже вызывается |
parseDouble падает |
Запятая или буквы | replace(',', '.') и try/catch |
main, зелёная стрелка Run. Если JDK не подхватился — File → Project Structure → SDK. Ошибки компиляции смотрите во вкладке Build.
Мини-проект: форма входа за один проход
Соберите одно окно «Учёт задач»:
- TodoList — список с добавлением и удалением (раздел).
- Меню Файл → Выход (MenuDemo).
- Строка состояния «Задач: N» — в
addBtnпослеaddElementобновляйтеstatusLabel. - При закрытии крестика —
showConfirmDialog(подтверждение выхода).
Скриншот окна + листинг = готовый отчёт по лабораторной «GUI на Java».
Маршрут изучения
| Шаг | Пример в статье | Дальше |
|---|---|---|
| 1 | Каркас | Первая программа |
| 2 | Метка + кнопка | Поле ввода |
| 3 | Конвертер | Список задач |
| 4 | Меню, диалоги | Справочник UI |
| 5 | Калькулятор | JavaFX для новых проектов |
Куда дальше
- Java — консольные задачи —
Scanner, массивы, сортировки - JavaFX и GUI — современный стек с Maven
- Справочник Swing —
JTable,JTabbedPane,JFileChooser - Простые приложения — викторина, файлы, Swing в энциклопедии
- Tkinter — окна и виджеты — те же идеи на Python
- C# WinForms и WPF — те же задачи на .NET
- Архитектура десктопа — окна, события, MVC