Java — Как сделать плавное переключение экранов на javaFX


Содержание

JavaFX: переключение между двумя панелями

Я разрабатываю «генератор случайных врагов» для доски D & D друзей, и так как я практикую Java, я хотел попробовать. Я хочу, чтобы он имел 2 якорные панели:

В первом вы даете значение следующим атрибутам объекта Foes:

После этого вы сохраняете эти выборы, и враги включаются в генератор.

  1. Вы генерируете случайного врага с его значениями и масштабируете согласно вашему уровню персонажа.

У меня вопрос, как я могу добраться от первого до второго? У меня есть довольно четкое представление о том, как разрабатывать как по отдельности, но не как их смешивать.

У меня просто есть код для второго, потому что изначально я не думал о его настройке. Я не думаю, что какой-либо код в отношении этого экрана уместен, но если вы хотите, просто скажите мне!

редактировать: я пытался самостоятельно, и мне удалось все, чтобы создать 2 файла FXML и установить контроллеры, но я получаю следующую ошибку, когда я нажимаю кнопку для переключения между панелями:

Элементы управления

Кнопки и метки

Наиболее часто используемые элементы управления в JavaFX — это, без сомнения, кнопки и метки. Кнопки представлены классом javafx.scene.control.Button и позволяют по нажатию выполнять некоторые действия. А метки представлены классы javafx.scene.control.Label , и их задача — вывод текстовой информации. Класс Button унаследован от классов ButtonBase, Labeled, Region, Control, Parent и Node, а класс Label — от Labeled, Region, Control, Parent и Node. JavaFX позволяет создавать самые разнообразные кнопки и метки: с текстом, графикой, и тем и другим, с различными стилями.

Класс Button имеет три конструктора:

Button() : создает кнопку без надписи

Button​(String text) : создает кнопку с определенной надписью

Button​(String text, Node graphic) : создает кнопку с определенной надписью и иконкой

Класс Label имеет три похожих конструктора:

Label() : создает метку без надписи

Label​(String text) : создает метку с определенной надписью

Label(String text, Node graphic) : создает метку с определенной надписью и иконкой

Ключевой возможностью кнопки является способность реагировать на нажатия пользователей и по нажтию выполнять некоторое действие. Для обработки нажатий в базовом классе ButtonBase определен метод setOnAction() , который устанавливает обработчик нажатия:

В качестве параметра в этот метод передается реализация интерфейса EventHandler:

Используем кнопку в программе:

В классе определена переменная-счетчик counter. И по нажатию на кнопку будет увеличиваться ее значение.

Занятие 8

Введение в библиотеку Swing

Библиотека Swing

Современные программы нуждаются в графическом интерфейсе пользователя (GUI). Пользователи отвыкли работать через консоль: они управляют программой и вводят входные данные посредством так называемых элементов управления (в программировании их также называют визуальными компонентами), к которым относятся кнопки, текстовые поля, выпадающие списки и т.д.

Каждый из современных языков программирования предоставляет множество библиотек для работы со стандартным набором элементов управления. Напомним, что под библиотекой в программировании набор готовых классов и интерфейсов, предназначенных для решения определенного круга задач.

В Java есть три библиотеки визуальных компонентов для создания графического интерфейса пользователя. Самая ранняя из них называется AWT. Считается, что при ее проектировании был допущен ряд недочетов, вследствие которых с ней довольно сложно работать. Библиотека Swing разработана на базе AWT и заменяет большинство ее компонентов своими, спроектированными более тщательно и удобно. Третья, самая новая библиотека, называется SWT.

Каждая библиотека предоставляет набор классов для работы с кнопками, списками, окнами, меню и т.д., но эти классы спроектированы по-разному: они имеют различный набор методов с разными параметрами, поэтому «перевести» программу с одной библиотеки на другую (например, с целью увеличения быстродействия) не так-то просто. Это почти как перейти с одного языка программирования на другой: все языки умеют делать одно и то же, но у каждого из них свой синтаксис, своя программная структура и свои многочисленные хитрости.

По этой причине вместо того, чтобы делать обзор всех трех библиотек, мы постараемся получше разобраться в одной из них — библиотеке Swing. Полноценный графический интерфейс может быть разработан с ее помощью.

Окно JFrame

Каждая GUI-программа запускается в окне и по ходу работы может открывать несколько дополнительных окон.

В библиотеке Swing описан класс JFrame , представляющий собой окно с рамкой и строкой заголовка (с кнопками «Свернуть», «Во весь экран» и «Закрыть»). Оно может изменять размеры и перемещаться по экрану.

В Swing есть еще несколько классов окон. Например, JWindow — простейшее окно, без рамки и без строки заголовка. Обычно с его помощью делается заставка к программе, которая перед запуском должна выполнить несколько продолжительных действий (например, загрузить информацию из БД).

Конструктор JFrame() без параметров создает пустое окно. Конструктор JFrame(String title) создает пустое окно с заголовком title .

Чтобы написать простейшую программу, выводящую на экран пустое окно, нам потребуется еще три метода:

setSize(int width, int height) — устанавливает размеры окна. Если не задать размеры, окно будет иметь нулевую высоту независимо от того, что в нем находится и пользователю после запуска придется растягивать окно вручную. Размеры окна включают не только «рабочую» область, но и границы и строку заголовка.

setDefaultCloseOperation(int operation) — позволяет указать действие, которое необходимо выполнить, когда пользователь закрывает окно нажатием на крестик. Обычно в программе есть одно или несколько окон при закрытии которых программа прекращает работу. Для того, чтобы запрограммировать это поведение, следует в качестве параметра operation передать константу EXIT_ON_CLOSE , описанную в классе JFrame .

setVisible(boolean visible) — когда окно создается, оно по умолчанию невидимо. Чтобы отобразить окно на экране, вызывается данный метод с параметром true . Если вызвать его с параметром false , окно снова станет невидимым.

Теперь мы можем написать программу, которая создает окно, выводит его на экран и завершает работу после того, как пользователь закрывает окно.

Обратите внимание, для работы с большинством классов библиотеки Swing понадобится импортировать пакет java.swing. *

Как правило, перед отображением окна, необходимо совершить гораздо больше действий, чем в этой простой программке. Необходимо создать множество элементов управления, настроить их внешний вид, разместить в нужных местах окна. Кроме того, в программе может быть много окон и настраивать их все в методе main() неудобно и неправильно, поскольку нарушает принцип инкапсуляции: держать вместе данные и команды, которые их обрабатывают. Логичнее было бы, чтобы каждое окно занималось своими размерами и содержимым самостоятельно. Поэтому классическая структура программы с окнами выглядит следующим образом:


В файле SimpleWindow.java:

В файле Program.java:

Из примера видно, что окно описывается в отдельном классе, являющемся наследником JFrame и настраивающее свой внешний вид и поведение в конструкторе (первой командой вызывается конструктор суперкласса). Метод main() содержится в другом классе, ответственном за управление ходом программы. Каждый из этих классов очень прост, каждый занимается своим делом, поэтому в них легко разбираться и легко сопровождать (т.е. совершенствовать при необходимости).

Обратите внимание, что метод setVisible() не вызывается в классе SimpleWindow , что вполне логично: за тем, где какая кнопка расположена и какие размеры оно должно иметь, следит само окно, а вот принимать решение о том, какое окно в какой момент выводится на экран — прерогатива управляющего класса программы.

Панель содержимого

Напрямую в окне элементы управления не размещаются. Для этого служит панель содержимого, занимающая все пространство окна * . Обратиться к этой панели можно методом getContentPane() класса JFrame . С помощью метода add(Component component) можно добавить на нее любой элемент управления.

В примерах этого занятия мы будем использовать только один элемент управления — кнопку (не вдаваясь в подробности ее устройства). Кнопка описывается классом JButton и создается конструктором с параметром типа String — надписью.

Добавим кнопку в панель содержимого нашего окна командами:

JButton newButton = new JButton(); getContentPane().add(newButton);

В результате получим окно с кнопкой. Кнопка занимает всю доступную площадь окна. Такой эффект полезен не во всех программах, поэтому необходимо изучить различные способы расположения элементов на панели.

Класс Container (контейнер)

Элементы, которые содержат другие элементы, называются контейнерами. Все они являются потомками класса Container и наследуют от него ряд полезных методов:

add(Component component) — добавляет в контейнер элемент component ;

remove(Component component) — удаляет из контейнера элемент component ;

removeAll() — удаляет все элементы контейнера;

getComponentCount() — возвращает число элементов контейнера.

Кроме перечисленных в классе Container определено около двух десятков методов для управления набором компонентов, содержащихся в контейнере. Как видно, они похожи на методы класса-коллекции. Это неудивительно, ведь по сути контейнер и является коллекцией, но коллекцией особого рода — визуальной. Кроме хранения элементов контейнер занимается их пространственным расположением и прорисовкой. В частности, он имеет метод getComponentAt(int x, int y) , возвращающий компонент, в который попадает точка с заданными координатами (координаты отсчитываются от левого верхнего угла компонента) и ряд других. Мы не будем подробно рассматривать абстрактный контейнер, а сразу перейдем к его наиболее часто используемому потомку — классу JPanel .

Класс JPanel (панель)

Панель JPanel — это элемент управления, представляющий собой прямоугольное пространство, на котором можно размещать другие элементы. Элементы добавляются и удаляются методами, унаследованными от класса Container .

В примере с кнопкой мы наблюдали, как добавленная на панель содержимого кнопка заняла все ее пространство. Это происходит не всегда. На самом деле у каждой панели есть так называемый менеджер размещения, который определяет стратегию взаимного расположения элементов, добавляемых на панель. Его можно изменить методом setLayout(LayoutManager manager) . Но чтобы передать в этот метод нужный параметр, необходимо знать, какими бывают менеджеры.

Менеджер последовательного размещения FlowLayout

Самый простой менеджер размещения — FlowLayout . Он размещает добавляемые на панель компоненты строго по очереди, строка за строкой, в зависимости от размеров панели. Как только очередной элемент не помещается в текущей строке, он переносится на следующую. Лучше всего пронаблюдать это на примере. Изменим конструктор класса SimpleWindow следующим образом:

Менеджеры расположения описаны в пакете java.awt. Не забывайте импортировать нужные классы.

Пронаблюдайте за поведением окна, появляющегося после запуска программы. Четыре кнопки в нем расположены как слова в текстовом редакторе (при выравнивании по центру). Эффект будет лучше заметен, если изменять размеры окна во время работы программы.

Проанализируем текст примера. Новый менеджер расположения FlowLayout создается конструктором без параметров. Обратите внимание, в программе не используется промежуточная переменная. То есть вместо двух команд:

FlowLayout newLayout = new FlowLayout(); panel.setLayout(newLayout);

Мы используем одну:

panel.setLayout( new FlowLayout());

Это вполне допустимо в тех случаях, когда в дальнейшем нам не потребуется обращаться к создаваемому объекту (что справедливо для данного примера). Мы создаем менеджер расположения, тут же привязываем его к панели — и все. Теперь панель и менеджер сами найдут друг с другом общий язык.

Цукерберг рекомендует:  Разбираем Underscore.js по косточкам. Метод every

Панель хранит ссылку на своего менеджера и сама обращается к нему каждый раз, когда нужно рассчитать координаты элементов (это происходит при их добавлении, удалении, изменении размеров, а также при изменении размеров окна). В принципе, мы можем даже получить этого менеджера методом getLayout() класса JPanel , но, как правило, в этом вообще нет необходимости.

Кстати, класс JPanel кроме конструктора без параметров, имеет конструктор, в котором в качестве параметра задается менеджер расположения. Поэтому вместо команд

JPanel panel = new JPanel(); panel.setLayout( new FlowLayout());

JPanel panel = new JPanel( new FlowLayout());

Более того, по умолчанию вновь создаваемая панель имеет именно менеджер расположения FlowLayout . Поэтому в приведенном выше примере мы устанаваем менеджера скорее для наглядности, вообще же, делать это не обязательно.

Точно также мы добавляем на панель новые кнопки. Мы нигде больше не пытаемся обратиться к этим кнопкам в программе, поэтому заводить под них переменные нет смысла.

Метод setContentPane(JPanel panel) позволяет заменить панель содержимого окна.

Менеджер граничного размещения BorderLayout

Менеджер размещения BorderLayout разделяет панель на пять областей: центральную, верхнюю, нижнюю, правую и левую. В каждую из этих областей можно добавить ровно по одному компоненту, причем компонент будет занимать всю отведенную для него область. Компоненты, добавленные в верхнюю и нижнюю области, будут растянуты по ширине, добавленные в правую и левую — по высоте, а компонент, добавленный в центр, будет растянут так, чтобы полностью заполнить оставшееся пространство панели.

При добавлении элемента на панель с менеджером размещения BorderLayout , необходимо дополнительно указывать в методе add() , какая из областей имеется в виду. Для этого служат строки с названиями сторон света: «North» , «South» , «East» , «West» и «Center» . Но вместо них рекомендуется использовать константы, определенные в классе BorderLayout : NORTH , SOUTH , EAST , WEST и CENTER (поскольку в строке можно допустить ошибку и не заметить этого, а при попытке написать неправильно имя константы компилятор выдаст предупреждение). Если же использовать метод add() как обычно, с одним параметром, элемент будет добавлен в центр.

Панель содержимого имеет именно такое расположение, именно поэтому кнопка и занимала все окно целиком (она была добавлена в центральную область). Чтобы пронаблюдать эффект BorderLayout , добавим кнопки во все пять областей:

Эффект будет хорошо наблюдаться, если изменять размеры окна.

Данное размещение не случайно используется в панели содержимого по умолчанию. Большинство программ пользуются областями по краям окна, чтобы расположить в них панели инструментов, строку состояния и т.п. А ограничение на один компонент в центральной области абсолютно не существенно, ведь этим компонентом может быть другая панель со множеством элементов и с любым менеджером расположения.

Менеджер табличного размещения GridLayout


GridLayout разбивает панель на ячейки одинаковой ширины и высоты (таким образом окно становится похожим на таблицу). Каждый элемент, добавляемый на панель с таким расположением, целиком занимает одну ячейку. Ячейки заполняются элементами по очереди, начиная с левой верхней.

Этот менеджер, в отличие от рассмотренных ранее, создается конструктором с параметрами (четыре целых числа). Необходимо указать количество столбцов, строк и расстояние между ячейками по горизонтали и по вертикали. Выполните следующий пример и пронаблюдайте эффект.

Менеджер блочного размещения BoxLayout и класс Box

Менеджер BoxLayout размещает элементы на панели в строку или в столбец.

Обычно для работы с этим менеджером используют вспомогательный класс Box , представляющий собой панель, для которой уже настроено блочное размещение. Создается такая панель не конструктором, а одним из двух статических методов, определенных в классе Box : createHorizontalBox() и createVerticalBox() .

Элементы, добавленные на панель с блочным размещением, выстраиваются один за другим. Расстояние между элементами по умолчанию нулевое. Однако вместо компонента можно добавить невидимую «распорку», единственная задача которой — раздвигать соседние элементы, обеспечивая между ними заданное расстояние. Горизонтальная распорка создается статическим методом createHorizontalStrut(int width) , а вертикальная — методом createVerticalStrut(int height) . Оба метода определены в классе Box , а целочисленный параметр в каждом из них определяет размер распорки.

Кроме того, на такую панель можно добавить еще один специальный элемент — своеобразную «пружину». Если размер панели будет больше, чем необходимо для оптимального размещения всех элементов, те из них, которые способны растягиваться, будут стараться заполнить дополнительное пространство собой. Если же разместить среди элементов одну или несколько «пружин», дополнительное свободное пространство будет распределяться и в эти промежутки между элементами. Горизонтальная и вертикальная пружины создаются соответственно методами createHorizontalGlue() и createVerticalGlue() .

Понять особенности работы этого менеджера лучше на наглядном примере. Мы расположим четыре кнопки вертикально, поставив между двумя центральными «пружину», а между остальными — распорки в 10 пикселов.

Особенности выравнивания элементов

В примере с вертикальной панелью все кнопки оказались выровнены по левому краю. Такое выравнивание по горизонтали принято по умолчанию.

Однако при разработке окна программы может понадобиться, чтобы какие-то элементы были выровнены иначе, например, по правому краю или по центру. Для того, чтобы установить выравнивание любого визуального компонента (например, кнопки или панели), используются методы setAlignmentX(float alignment) — выравнивание по горизонтали и setAlignmentY(float alignment) — выравнивание по вертикали. В качестве параметра проще всего использовать константы, определенные в классе JComponent . Для выравнивания по горизонтали служат константы LEFT_ALIGNMENT (по левому краю), RIGHT_ALIGNMENT (по правому краю) и CENTER_ALIGNMENT (по центру). Для выравнивания по вертикали — BOTTOM_ALIGNMENT (по нижнему краю), TOP_ALIGNMENT (по верхнему краю) и CENTER_ALIGNMENT (по центру).

Однако выравнивание работает несколько иначе, чем ожидается. Чтобы это обнаружить, изменим предыдущий пример, выровняв третью кнопку по правому краю. Для этого заменим строку:

box.add( new JButton( «-» ));

JButton rightButton = new JButton( «-» ); rightButton.setAlignmentX(JComponent.RIGHT_ALIGNMENT); box.add(rightButton);

Нам пришлось ввести переменную для обращения к этой кнопке, поскольку теперь нам нужно выполнить с ней не одно, а два действия: установка выравнивания по правому краю и добавление в панель. Прежний прием — одновременное создание кнопки и передача ее в качестве параметра в метод — здесь не сработает.

После запуска программы мы увидим окно, в котором кнопки расположены не так, как, наверное, ожидалось. Мы привыкли, что выравнивание по правому краю прижимает объект к правому краю контейнера, но в данном случае перестроились все элементы, причем кнопка с выравниванием по правому краю оказалась самой левой.

Объяснение просто. При выравнивании по правому краю объект не прижимается к правому краю компонента. Вместо этого он прижимается правым краем к невидимой линии выравнивания. Все остальные компоненты прижимаются к этой линии своим левым краем, поэтому и получается наблюдаемый эффект.

Единственная трудность для начинающего разработчика может оказаться в том, что не всегда легко понять, где именно пройдет эта линия. Ее положение зависит от размеров и выравнивания всех элементов контейнера. Однако легко запомнить простое правило: если все элементы в контейнере выровнены одинаково, мы получим привычное поведение (как это и было в предыдущем примере, когда все компоненты были выровнены влево и линия в результате прижалась к левому краю панели.

Параметр выравнивания на самом деле представляет собой вещественное число в диапазоне от 0 до 1. Он показывает, какая часть компонента окажется слева от линии выравнивания, т.е. в каких пропорциях компонент будет «разрезан». Константы LEFT_ALIGNMENT и TOP_ALIGNMENT на самом деле равны 0, RIGHT_ALIGNMENT и BOTTOM_ALIGNMENT равны 1, а CENTER_ALIGHNMENT — 0.5. Можно подставлять эти числа напрямую (хотя использование констант значительно повышает наглядность!), а можно выбрать любое другое число от 0 до 1 и настроить совершенно произвольное выравнивание.

Попробуйте поэкспериментировать с вертикальной панелью, задавая различное выравнивание для ее элементов, чтобы интуитивно понять логику размещения линии выравнивания. Изменяйте размеры окна во время работы программы, чтобы увидеть как меняется положение этой линии.

Ручное размещение элементов

Если в качестве менеджера размещения панели установить null , элементы не будут расставляться автоматически. Координаты каждого элемента необходимо в этом случае указать явно, при этом они никак не зависят от размеров панели и от координат других элементов. По умолчанию координаты равны нулю (т.е. элемент расположен в левом верхнем углу панели). Размер элемента также необходимо задавать явно (в противном случае его ширина и высота будут равны нулю и элемент отображаться не будет).

Координаты элемента можно задать одним из следующих методов:

setLocation(int x, int y) ,

Эти методы работают аналогично, устанавливая левый верхний угол элемента в точку с заданными координатами. Разница в способе задания точки. Можно представить точку двумя целыми числами, а можно объектом класса Point . Класс Point по сути представляет собой ту же пару чисел, его конструктор имеет вид Point(int x, int y) . Получить доступ к отдельной координате можно методами getX() и getY() .

Можно задаться вопросом: зачем использовать класс Point , если можно просто передать пару чисел? Но дело в том, что многие полезные методы возвращают результат — координаты некоторой точки — в виде объекта этого класса. Например, метод getLocation() , возвращающий координаты элемента. Предположим, нам нужно поместить элемент b в точности в то место, которое занимает элемент a . Этого легко добиться одной строкой:

Размер элемента задается одним из двух методов:

setSize(int width, int height) ,

Эти методы работают одинаково — разница, как и в прошлый раз, в способе передачи параметра. Класс Dimension , аналогично классу Point , просто хранит два числа, имеет конструктор с двумя параметрами: Dimension(int width, int height) и позволяет получить доступ к своим составляющим — ширине и высоте — с помощью простых методов getWidth() и getHeigth() . Для того, чтобы получить текущий размер элемента, можно воспользоваться методом getSize() , возвращающего объект класса Dimension . Элемент b можно сделать точно такого же размера, как элемент a , выполнив команду:

Создадим панель, с которой не будет связано никакого менеджера размещения и вручную разместим на ней две кнопки:

Мы используем одну и ту же переменную button для обращения к обеим кнопкам (причем, второй раз ее описывать не нужно). В самом деле, осуществив все необходимые операции с первой кнопкой и зная, что обращаться к ней нам больше не понадобится, мы используем «освободившуюся» переменную для манипуляций со второй.

Автоматическое определение размеров компонентов

Если у панели есть любой менеджер размещения, она игнорирует явно заданные размеры и координаты всех своих элементов. В этом легко убедиться, заменив в предыдущем примере команду panel.setLayout( null ) на panel.setLayout( new FlowLayout()) . Менеджер размещения сам определяет координаты и размеры всех элементов.

Способ определения координат элементов очевидным образом вытекает из алгоритмов работы каждого менеджера и, таким образом, детально рассмотрен нами выше.

Мы также отмечали, что в некоторых случаях компоненты стараются заполнить все доступное им пространство. Например, всю центральную область в случае менеджера BorderLayout или всю ячейку в менеджере GridLayout . А в панели с менеджером FlowLayout , напротив, элементы никогда не пытаются выйти за определенные границы. Рассмотрим, что это за границы.

Каждый визуальный компонент имеет три типа размеров: минимально допустимый, максимально допустимый и предпочтительный. Узнать, чему равны эти размеры для данного компонента можно с помощью соответствующих методов:

Методы возвращают результат типа Dimension . Они запрограммированы в соответствующем классе. Например, у кнопки минимальный размер — нулевой, максимальный размер не ограничен, а предпочтительный зависит от надписи на кнопке (вычисляется как размер текста надписи плюс размеры полей).

Менеджер FlowLayout всегда устанавливает предпочтительные размеры элементов. Менеджер BorderLayout устанавливает предпочтительную ширину правого и левого, а также предпочтительную высоту верхнего и нижнего. Остальные размеры подгоняются под доступное пространство панели. Менеджер GridLayout пытается подогнать размеры всех элементов под размер ячеек. Менеджер BoxLayout ориентируется на предпочтительные размеры.

Цукерберг рекомендует:  Frontend - Разница между Frontend-разработчиком и Web-разработчиком

Когда элемент старается занять все доступное ему пространство, он «учитывает» пожелания не делаться меньше своих минимальных или больше максимальных.

Всеми тремя размерами можно управлять с помощью соответствующим методов set:

Чаще всего используется простой прием, когда элементу «не рекомендуется» увеличиваться или уменьшаться относительно своих предпочтительных размеров. Это легко сделать командой:

«Упаковка» окна

В рассмотренных выше примерах мы явно задавали размер окна методом setSize() . Но когда используется какой-либо менеджер расположения, расставляющий элементы и изменяющий их размеры по собственным правилам, трудно сказать заранее, какие размеры окна будут самыми подходящими.


Безусловно, наиболее подходящим будет вариант, при котором все элементы окна имеют предпочтительные размеры или близкие к ним * .

Если вместо явного указания размеров окна, вызвать метод pack() , они будут подобраны оптимальным образом с учетом предпочтений всех элементов, размещенных в этом окне.

Оцените работу этого метода, заменив в каждом из вышеприведенных примеров команду

Заметьте, что когда панель не имеет метода размещения, эта команда не работает (поскольку панель не имеет алгоритма для вычисления своего предпочтительного размера).

Упражнение

Как уже отмечалось, элементом панели может быть другая панель. Создайте панель с тремя кнопками и менеджером размещения FlowLayout и панель с двумя кнопками и менеджером размещения BoxLayout (горизонтальным). Разместите обе панели в главном окне (не изменяя менеджера размещения у панели содержимого): одну в центр, а другую вдоль любой стороны окна.

Рамки

Когда панели служат не просто для размещения элементов в соответствии с алгоритмом некоторого менеджера, а для визуального отделения их друг от друга, они оформляются с помощью рамок.

Рамка панели устанавливается методом setBorder(Border border) . Параметром метода выступает рамка — объект класса Border . Это абстрактный класс, поэтому для создания рамки используются его наследники:

EmptyBorder — пустая рамка, позволяет создать отступы вокруг панели. Размеры отступов задаются в конструкторе четырьмя целыми числами.

TitledBorder — рамка с заголовком. Простейший конструктор имеет один параметр типа String (текст заголовка). Заголовок может размещаться вдоль любой стороны рамки, иметь различные начертания.

EtchedBorder — рамка с тиснением. Может быть вогнутой или выпуклой.

BevelBorder — объемная рамка (выпуклая или вогнутая). Можно настроить цвета, требуемые для получения объемных эффектов.

SoftBevelBorder — то же самое, что BevelBorder, но позволяет дополнительно скруглить углы.

LineBorder — простая рамка, нарисованная сплошной линией. Можно выбирать цвет и толщину линии, скруглить углы.

MatteBorder — рамка из повторяющегося рисунка.

CompoundBorder — объединяет две рамки, передаваемые в качестве параметров конструктору в одну новую рамку.

Все перечисленные классы описаны в пакете javax.swing.border.

Рассмотрим пример. В этом примере мы создадим шесть панелей с различными рамками и разместим их в виде таблицы. Чтобы не описывать шесть раз процедуру создания новой панели, вынесем ее в отдельный метод:

private JPanel createPanel(Border border, String text)

Метод createPanel() создает панель с кнопкой во весь свой размер. В качестве параметра передается надпись на кнопке и рамка, которую необходимо добавить к панели. Рамка добавляется не напрямую, а путем композиции с пустой рамкой. Этот прием часто используется, чтобы рамка не прилипала к краю панели.

Теперь шесть раз воспользуемся этим методом в конструкторе окна программы.

Этот пример показывает, с помощью каких конструкторов создаются различные рамки и как они выглядят. В нем использованы два новых класса: Color и ImageIcon .

Класс Color предназначен для работы с цветом. В нем есть несколько констант, описывающих наиболее распространенные цвета. В частности, к таковым относится Color.ORANGE .

Класс ImageIcon описывает графическое изображение. Параметр его конструктора — это путь к файлу, из которого изображение может быть загружено. В примере используется относительное имя файла «1.gif». Чтобы объект ImageIcon был успешно создан, файл с таким именем должен быть помещен в папку проекта.

Suvitruf’s Blog :: Gamedev suffering

Блог о разработке игр и серверных технологиях

libGDX: Часть 8. Создание меню и переход между экранами

В любой игре присутствует меню. Довольно сложно придумать иной способ навигации. В этой статье рассмотрим как создать свой экран с меню средствами libGDX. Попутно немного о проблеме соотношения сторон на различных устройствах.

Проблема с разрешением экрана

Основная проблема, с которой сталкиваются разработчики игр для платформы Android — неправильное отображение сцены на устройствах с разным соотношением сторон. Если вы посмотрите разрешения на различных устройствах, то обнаружите, что их диапазон довольно большой.

Ладно ещё 720×1280 можно без проблем масштабировать до 360×640. Но простым скалированием не всегда можно решить проблему. Каждый выкручивается по своему. Можно сцену размещать по центру и добавлять фоновые картинки по краям. Или по краю выравнивать, а с другого края фоновое что-то. В моих играх такой проблемы не было, просто видимая часть объектов на различных устройства различалась. На геймплей это не особо сказывалось.

Переключение между экранами

Переключение между экранами в LibGDX довольно простое. Надо вызвать метод setScreen(Screen screen);. То есть в классе игры будут ссылки на все возможные экраны:

По сути, создание меню не особо отличается от экрана самой игры. Так же обрабатываем нажатия, рендерим и т.д. Создадим класс IntroScreen, реализовав Screen, InputProcessor. Возьмём за основу решение, которое используется в игре Defender 2. Фон 512×1024 размером. Сама пикча на этом спрайте 480×800. Если экран больше этой картинки, то справа и снизу будет чёрный фон.

Создание меню

Размеры камеры зададим для актуальной картинки фоновой. Всё остальное схоже с игровым экраном.

Необходимо нарисовать сам фон.

Поверх него вывести кнопку.

downBtn показывает нажата ли кнопка или нет. Для красоты анимации, так сказать (: Теперь надо только обработать нажатия.

В целом работа с меню ничем не отличается от обработки нажатий и отрисовка на игровом экране. Многие меню делают не средствами OpenGL, а не уровне Вьюх. То есть, при запуске игры открывает Activity с лейаутами. С таким меню работать в принципе проще. А уже потом при нажатии на кнопку открывать другое Activity и загружать в нём OpenGL.

Переключение между панелями в JavaFX

Я пытаюсь сделать программу на Java в JavaFX, используя FXML. Однако у меня возникли проблемы с управлением макетом. Я хочу переключаться между панелями, как я привык с CardLayout в разгаре, но, похоже, я не могу этого понять.


Я погуглил и не нашел ответов.

Есть ли какой-либо эквивалент CardLayout в JavaFX? и если да, можете ли вы привести пример? Это очень поможет моему вечеру!

Вот мой код FXML

Не анимированные переходы

Если вам не нужны анимированные переходы между панелями, вы можете:

  1. Замените всю сцену, создав новую сцену и установите эту сцену на вашей сцене ИЛИ
  2. Замените только определенную панель в родительском макете, удалив старую панель из родительского и добавив новую (манипулируя списком дочерних элементов родителя ) ИЛИ
  3. Поместите все свои панели в StackPane и переместите панель, которую вы хотите отобразить, в верхнюю часть дочернего списка стека .

Если вы хотите анимированные переходы между панелями, посмотрите две серии статей Анджелы Кайседо по управлению несколькими экранами в JavaFX:

Решение Анджелы состоит в том, чтобы использовать StackPane с отдельным пользовательским классом ScreenController для управления переходами или анимациями между панелями в стеке.

Такие фреймворки, как JFXFlow и WebFX также могут предоставлять интерфейс в стиле браузера для вашего приложения, позволяя пользователям переключаться между экранами назад и вперед с помощью кнопок «назад» и «вперед» и списка истории.

Я думаю, что разработка на обеих упомянутых выше платформах теперь не существует. Другие структуры, которые находятся в стадии разработки:

И многие другие (я не буду приводить полный список здесь).

Вот как я это делаю: (В этом примере я создал два документа FXML с соответствующими им контроллерами. Они называются FXMLLogin.fxml и Home.fxml соответственно).

Итак, чтобы перейти от FXMLLogin к дому,

В этом примере я создал метод в FXMLLoginController, который реагирует на нажатие кнопки «войти» в этой форме:

Обратите внимание, что @FXML чрезвычайно важен.

Если я правильно понял ваш вопрос, то это должно сработать.

Переключение между панелями совсем не очевидно, и оно четко не указано ни в одном учебнике в Интернете, который я нашел. Мне пришлось много гуглить сам, прежде чем я понял это в первый раз. К счастью, на самом деле все довольно просто, когда вы освоитесь.

Надеюсь я не правильно понял ваш вопрос? Дайте мне знать, если это то, что вам нужно :)

JRebirth Application Framework предоставляет пользовательский «CardLayout», используя свой выделенный шаблон wB-CSMvc.

Класс StackModel выполнит работу (предоставленную артефактом org.jrebirth.af:component), вы можете найти 2 варианта использования здесь и здесь .

Каждая модель ‘card’ может быть вызвана с использованием идентификатора enum | modelKey, и каждый стек имеет уникальное имя.

Первый пример используется для демонстрационного приложения JRebirth , это довольно простое приложение, которое позволяет отображать другие демонстрационные приложения JRebirth, динамически загружаемые как модуль JRebirth (из отдельного и независимого jar-файла).

Это приложение загрузит свою первую модель (MainModel) и поместит свой корневой узел в корневой узел сцены (StakPane, автоматически созданный).

MainModel перечислит все подмодули приложения, чтобы добавить записи кнопок в свое левое меню, и StackModel, который будет отображать содержимое каждого модуля StackModel загружается с использованием специальной аннотации с использованием уникального ключа String.

MainView будет отвечать за создание меню модуля:

А MainController будет загружать содержимое модуля при нажатии любой кнопки меню:

Второй пример загрузит StackModel как innerComponent, и каждая карта будет идентифицирована записью enum (сохраненной в FXMLPage), давайте посмотрим FXMLShowCaseModel:

Перечисление, связывающее запись enum с Model:

Поскольку список карточек известен, элемент панели инструментов статически создается в FXMLShowCaseView, а обработка событий также статически определяется в FXMLShowCaseController с использованием другого метода:

Дайте мне знать, если у вас есть какие-либо вопросы

Использование JFrame для создания окна приложения

Каждое десктопное приложение должно иметь окно. В этом окне будут располагаться все необходимые компоненты графического интерфейса пользователя, посредством которых пользователь будет работать с приложением. Попробуем создать окно нашего приложения и разместить там что-нибудь. Пока что наше приложение будет простым и незамысловатым. Для создания окна приложения в Swing используется класс JFrame. Он содержит ряд методов и свойств, которые позволяют настроить его должным образом. Рассмотрим пример.

import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestFrame <

public static void createGUI() <
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame(«Test frame»);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JLabel label = new JLabel(«Test label»);
frame.getContentPane().add(label);

frame.setPreferredSize(new Dimension(200, 100));

public static void main(String[] args) <
javax.swing.SwingUtilities.invokeLater(new Runnable() <
public void run() <
createGUI();
>
>);
>
>

Это самое простое Swing приложение. Данный код создаст приложение, внешний вид которого представлен на рисунке. Рассмотрим код более детально. Каждое приложение должно содержать статический метод main – точка входа приложения, именно с него начинается выполнение.

Далее выполняется создание графического интерфейса пользователя. Создание графического интерфейса пользователя непременно должно происходить в Event dispatch потоке. Для этого метод вызывается внутри определенного вида конструкции SwingUtilities. Перейдем к непосредственному созданию и размещению компонентов.

Самой первой строкой метода createGUI мы говорим системе, чтобы окно полностью рисовалось Swing. Если закомментировать этот код, то окно будет определяться самой операционной системой – Swing доверит рисовать окно ей. Далее создаем само окно и указываем текст, который будет располагаться в его заголовке. С помощью метода setDefaultCloseOperation мы говорим системе, как отреагировать на закрытие окна. Сейчас нам необходимо, чтобы при закрытии окна закрывалось и приложение. Для этого мы передаем параметр JFrame.EXIT_ON_CLOSE. Но когда-нибудь необходимо будет не закрывать приложение, а закрыть только окно и оставить выполняться его в фоновом режиме, тогда мы будем передавать этому методу другой параметр.

Цукерберг рекомендует:  Макет с горизонтальной прокруткой

Далее создаем текстовый лейбл с помощью JLabel, указывая при этом какой текст мы хотим в нем видеть, и размещаем на форме. При размещении компонента в окне тоже есть одна хитрость. У объекта JFrame есть специальная панель content pane, на которой должны размещаться все остальные дочерние компоненты. С помощью вызова getContentPane мы получаем эту панель и добавляем лейбл уже на нее. Далее устанавливаем размер окна и показываем его пользователю.


Иногда история создания интернета интересна к прочтению. Можно много узнать о том, как создавали интернет.

Блог только про Java

Учимся программировать на Java с нуля

Создание диалоговых окон в Java

Как вы наверное уже знаете, для использования предопределенных диалоговых окон применяется класс JOptionPane. Теперь мы опишем, как «вручную» создать собственное диалоговое окно.

На рис.1 показано типичное модальное диалоговое окно, содержащее сообщение. Подобное окно отображается на экране после того, как пользователь выбрал пункт меню About.

Для того чтобы реализовать такое окно, необходимо создать подкласс класса JDialog. По сути, это тот же процесс, которым мы воспользовались для создания главного окна приложения, расширяя класс JFrame.

Точнее говоря, нужно сделать следующее:

  1. В конструкторе вашего диалогового окна вызовите конструктор суперкласса JDialog. Добавьте в диалоговое окно компоненты пользовательского интерфейса.
  2. Добавьте обработчики событий.
  3. Задайте размер диалогового окна.

При вызове конструктора суперкласса нужно указать фрейм-владелец, заголовок окна и признак модальности.

Фрейм-владелец управляет местом отображения диалога. Вы можете указать null вместо владельца — тогда диалог будет принадлежать скрытому фрейму.

Признак модальности указывает на то, должны ли блокироваться другие окна вашего приложения, пока отображается диалог. Немодальные окна не блокируют другие окна.

Модальный диалог блокирует все остальные окна приложения(за исключением дочерних по отношению к этому диалогу). Вы используете немодальные диалоги для создания панелей инструментов, к которым постоянно открыт доступ.

С другой стороны, модальные диалоги вы будете использовать, чтобы вынудить пользователя ввести необходимую информацию, прежде чем продолжить работу приложения.

Начиная с Java SE 6, добавлены два дополнительных типа модальности. Документо-модальный диалог блокирует все окна, относящиеся к одному «документу», или, точнее говоря, все окна с тем же родительским корневым окном, что и у данного диалога.

Это решает проблему систем помощи. В более старых версиях пользователи не могли взаимодействовать с окнами справки, когда всплыли модальный диалог. Toolkit-модальный диалог блокирует все окна их одного и того же «toolkit»(набора инструментов).

Toolkit — это программа Java, запускающая несколько приложений, такая как механизм аплетов в браузере. Дополнительную информацию на эту тему можно найти по адресу http://www.oracle.com/technetwork/java/index.html

Рис.1. Диалоговое окно About

Ниже приведен фрагмент программы, создающая диалоговое окно:

Как видите, конструктор добавляет элементы пользовательского интерфейса, в данном случае — метки и кнопку. Кроме того, он добавляет обработчик кнопки и задает размер окна.

Для того чтобы отобразить диалоговое окно на экране, необходимо создать новый объект JDialog и вызвать метод setVisible():

Фактически в программе, рассматриваемой здесь в качестве примера, диалоговое окно создается только единожды, а затем мы используем его повторно каждый раз, когда пользователь щелкает на кнопке About:

Когда пользователь щелкает на кнопке ОК, диалоговое окно должно закрываться. Эта реакция определяется в обработчике событий, связанных с кнопкой ОК:

Когда пользователь закрывает окно диалога, щелкая на кнопке Close, оно исчезает с экрана. Как и в классе JFrame, программист может изменять эту реакцию с помощью метода setDefaultCloseOperation().

Программа, демонстрирующая использование диалогового окна About, приведена ниже:

Один комментарий на “ Создание диалоговых окон в Java ”

На основе класса Thread, как создать пустое окно, которое произвольно двигаться в пределах монитора?

Переключение между экранами на комбинированном нажатии клавиши в JavaFX

Я хочу, чтобы переключаться между двумя сценами по нажатию Ctrl + D и вот мой код: Основной Класс:

Он отлично работает. Но когда я хочу получить обратно от СЦЕНЫ2 к СЦЕНЫ1, код не работает. Вот мой код контроллера СЦЕНЫ2:

initialize() Метод вызывается как часть процесса загрузки, т.е. вызывается во время выполнения

Очевидно, что это происходит , прежде чем добавлять root1 к сцене, поэтому , когда вы делаете

label1.getScene() возвращается null и вы получите исключение нулевого указателя.

Добавьте обработчик события к сцене, когда вы создаете сцену. Вы можете повторно использовать код, если вы поместите его в метод в классе своего приложения:

А потом просто удалить обработчик события из initialize() метода.

Использование JFrame для создания окна приложения

Каждое десктопное приложение должно иметь окно. В этом окне будут располагаться все необходимые компоненты графического интерфейса пользователя, посредством которых пользователь будет работать с приложением. Попробуем создать окно нашего приложения и разместить там что-нибудь. Пока что наше приложение будет простым и незамысловатым. Для создания окна приложения в Swing используется класс JFrame. Он содержит ряд методов и свойств, которые позволяют настроить его должным образом. Рассмотрим пример.

import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestFrame <


public static void createGUI() <
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame(«Test frame»);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JLabel label = new JLabel(«Test label»);
frame.getContentPane().add(label);

frame.setPreferredSize(new Dimension(200, 100));

public static void main(String[] args) <
javax.swing.SwingUtilities.invokeLater(new Runnable() <
public void run() <
createGUI();
>
>);
>
>

Это самое простое Swing приложение. Данный код создаст приложение, внешний вид которого представлен на рисунке. Рассмотрим код более детально. Каждое приложение должно содержать статический метод main – точка входа приложения, именно с него начинается выполнение.

Далее выполняется создание графического интерфейса пользователя. Создание графического интерфейса пользователя непременно должно происходить в Event dispatch потоке. Для этого метод вызывается внутри определенного вида конструкции SwingUtilities. Перейдем к непосредственному созданию и размещению компонентов.

Самой первой строкой метода createGUI мы говорим системе, чтобы окно полностью рисовалось Swing. Если закомментировать этот код, то окно будет определяться самой операционной системой – Swing доверит рисовать окно ей. Далее создаем само окно и указываем текст, который будет располагаться в его заголовке. С помощью метода setDefaultCloseOperation мы говорим системе, как отреагировать на закрытие окна. Сейчас нам необходимо, чтобы при закрытии окна закрывалось и приложение. Для этого мы передаем параметр JFrame.EXIT_ON_CLOSE. Но когда-нибудь необходимо будет не закрывать приложение, а закрыть только окно и оставить выполняться его в фоновом режиме, тогда мы будем передавать этому методу другой параметр.

Далее создаем текстовый лейбл с помощью JLabel, указывая при этом какой текст мы хотим в нем видеть, и размещаем на форме. При размещении компонента в окне тоже есть одна хитрость. У объекта JFrame есть специальная панель content pane, на которой должны размещаться все остальные дочерние компоненты. С помощью вызова getContentPane мы получаем эту панель и добавляем лейбл уже на нее. Далее устанавливаем размер окна и показываем его пользователю.

Иногда история создания интернета интересна к прочтению. Можно много узнать о том, как создавали интернет.

GUI в Java c помощью JFace: Создание окна приложения

JFace — это доплнительный слой абстракции над графической библиотекой SWT, предоставляющий возможности для разработки графического интерфейса приложения на основе модели MVC(Model View Controller). Основные компоненты JFace включают:

  • Viewers — классы для инкапсуляции задач предоставления данных для отображения, их фильтрации, сортировки и т.п.
  • Actions and contributions — вводят семантику описания пользовательских действий и того, как они должны быть доступны пользователю.
  • Image and font registries — предоставляют классы для управления ресурсами, такими как изображения и шрифты.
  • Dialogs and wizards — фреймворк для построения сложного диалогового взаимодействия с пользователем.
  • Field assist — предоставляет возможности для реализации вспомогательной функциональности для полей, такой как отображение статуса поля или подсказки о содержимом.

В первой части будет рассмотрено создание простого окна с использованием JFace, добавление к нему меню, статусной строки и панели инструментов.

Настройка проекта

Для того, чтобы разрабатывать графические приложения с использованием JFace в Eclipse, необходимо подключить jar-файлы SWT и JFace.

  • В случае, если в Eclipse установлено PDE, то это можно сделать, указав в настройках проекта использовать библиотеку SWT, и поставить галочку для поддержки JFace.
  • Если же PDE не установлен, то необходимо подключить jar-файлы к проекту вручную. Найти их можно в директории plugins эклипса, называются они org.eclipse.swt_*.jar и org.eclipse.jface_*.jar

Создание окна

Окно приложения в JFace наследуется от класса ApplicationWindow, предоставляющего возможности для создания меню, панелей управления и строки статуса.

Простейший вариант создания окна приведен в следующем примере:

Создание содержимого окна

Для того, чтобы создать какое-то содержимое окна, необходимо переопределить метод Control createContents( Composite parent ) класса ApplicationWindow. Метод должен возвращать компонент, который будет являться содержимым окна.

В этом же методе можно установить и заголовок окна, вызвав метод setText( String text ) шелла, доступного по вызову getShell()

В этом примере таким компонентом будет просто метка белого цвета, в реальных приложениях таким компонентом является какой-нибудь композит.

Добавление статусной строки

Добавление к окну приложения статусной строки реализуется не просто, а очень просто. Для этого надо всего-навсего вызвать защищенный метод addStatusBar(). Наверное, наиболее подходящим местом для такого вызова является конструктор окна, или какой-нибудь метод его инициализации.

Для того, чтобы отобразить текст в статусной строке необходимо вызвать метод setStatus( String status ), аргументом которого и является та самая строка, которую необходимо отобразить.

Создание меню

Для создания строки меню в JFace необходимо, вызвать метод addMenuBar(), как и для создания строки статуса.
Но затем необходимо добавить пункты меню на панель. Осуществляется это следующим образом:

  • Раздел меню описывается классом MenuManager. В конструкторе ему может быть передана строка — имя раздела, где символ «&» означает, что следующий за ним символ будет ключом при навигации с помошью клавиши Alt. Добавляется раздел меню на панель с помощью конструкции getMenuBar().add( menu ).
  • Пункт меню описывается классом Action. Сам класс является абстрактным, пункт меню должен быть унаследован от него и переопределять метод vo >В следующем примере мы создаем раздел меню File и один пункт Hello в нем, выбор которого вызывает появление текста в статусной строке окна. Код создания меню я оформил в один метод, который вызывается из конструктора окна:

Создание панели инструментов

Для того, чтобы создать панель инструментов в окне необходимо в конструкторе окна вызвать метод addToolBar( int style ), в который передать стиль компонента панели.

Для доступа к созданной панели используется метод getToolBarManager(). Для добавления действия на панель используется метод add панели, куда передается действие.

В простейшем случае создание панели и добавление на нее кнопки будет выглядеть:

Создание нескольких перемещаемых панелей инструментов

Вместо одной панели инструментов можно создать набор перемещаемых панелей (CoolBar). Для этого необходимо:

  1. Вместо метода addToolBar вызвать метод addCoolBar
  2. Для доступа к набору панелей используется метод getCoolBarManager()
  3. Создать панель инструментов, на которую можно будет добавлять действия. Для этого необходимо создать новый экземпляр класса ToolBarManager, который будет представлять панель и вызвать метод add у CoolBarManager, передав туда панель.
  4. На созданную панель можно добавлять действия

Пример кода, создающего две плавающие панели:

Важно! Окно приложение может иметь или одну панель управления или набор перемещаемых, попытка создания и того и другого приведет к ошибке!

Возможные проблемы

Здесь будут описаны некоторые проблемы, с которыми можно столкнуться:

  • При добавлении пунктов меню после запуска приложения они не появляются — чтобы изменения меню после создания окна отобразились на нем, необходимо вызвать метод getMenuBarManager().update( true ) — указать обновить панель меню.

Ссылки

Дополнительная информация по JFace может быть найдена по следующим ссылкам:

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих