Лабораторная работа. Создание современного пользовательского интерфейса с JavaFX — КиберПедия 

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...

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

Лабораторная работа. Создание современного пользовательского интерфейса с JavaFX

2022-10-10 59
Лабораторная работа. Создание современного пользовательского интерфейса с JavaFX 0.00 из 5.00 0 оценок
Заказать работу

Реализация паттерна MVC. - Откройте проект JavaFXApp в каталоге Лабы Java2/JavaFX/Lab1. - Запустите его, обратите внимание, что весь пользовательский интерфейс создаётся программно в методе createPane() класса JavaFXApp. В этом же классе находятся и обработчики на кнопки. - Удалите/закомментируйте эти обработчики и метод createPane(). - Закомментируйте строку кода в методе start(), в которой вызывается метод createPane(). - Удалите ненужные директивы import. - Добавьте в пакет(javafxapp) проекта новый элемент – Пустой файл FXML. Установите его имя в GridPane, нажмите далее и выберите опцию – Использовать новый контроллер. Нажмите далее и готово. - Откройте текст сгенерированного класса контроллера и добавьте в него следующий код: · СоздайтевклассеметодpublicvoidbtnFindClick(ActionEventevent){} · Перед методом поставьте аннотацию @FXML, что позволит использовать имя этого метода в fxml файле;  · Создайте второй такой же метод с именем btnCancelClik; · Добавьте необходимые директиве import. Важно: это должен быть пакет javafx! - Откройте файл GridPane.fxml. - Добавьте в него следующую директиву import: <?importjavafx.scene.text.*? > - Замените корневой тег на GridPane. - В открывающем теге GridPane добавьте следующие атрибуты:            fx:id="root" prefHeight="550.0" pref alignment="CENTER" hgap="10" vgap="10" - Для задания отступов элементов управления друг от друга поместите в корневой тег GridPane следующий текст:            <padding>                           <javafx.geometry.Insets top="25" right="25" bottom="25" left="25"/>            </padding> - Нижедобавьтеэлемент<Text text= "File finder" style="-fx-font: NORMAL 20 Tahoma;" />, вкоторомзадайте, чтоэлементрасположенвнулевомстолбцеинулевойстроке GridPane иобъединяетдвастолбцаиоднустроку GridPane. - Добавьте <Labeltext="Inputpath:" /> в нулевой столбец первой строки. - Добавьте <TextField fx:id="pathId" text="C:\Program Files" /> в первый столбец первой строки. - Добавьте <Labeltext="Fileendswith:" /> в нулевой столбец второй строки. - Добавьте <TextFieldfx:id="endId" text=".pdf" /> в первый столбец второй строки. - Добавьте <Button text="Find" /> в нулевой столбец третьей строки. Для привязки события создайте в этом элементе атрибут onAction="". Внутри кавычек поставьте # и нажмите Ctrl+Продел, выберите из списка нужный обработчик для события. - Ниже вставьте следующий текст: <HBoxGridPane.columnIndex="1" GridPane.rowIndex="3"> <Button text="Cancel" onAction="#btnCancelClick"/> <ProgressBar fx:id="barId" minprogress="0" translateX="100" /> </HBox> <ListView fx:id="listId" min GridPane.columnIndex="0" GridPane.rowIndex="4" GridPane.columnSpan="2" GridPane.rowSpan="1" > </ListView> - Запустите программу. Результат должен быть идентичен исходному варианту.

 

Идем далее…

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

Открываем проект: Java2-02\Лабы Java2\3-JavaFX\Lab1\JavaFXApp

Сразу как проект загрузится, нажимаете запуск и смотрите, что получается на экране:

Этой программой мы будем заниматься сегодня и завтра. И в конце концов эта программа должна начать работать. Что она будет делать? Она будет искать в каталоге файлы с указанным расширением. И так как это долгоиграющая операция, пока мы не сделаем асинхронно с помощью потоков, она будет у нас блокировать пользовательский интерфейс. Сейчас программа ничего не блокирует, потому что функционал поиска здесь отсутствует, но обработчики подписаны.

В чем состоит наша задача в этом первом варианте лабораторной работы? А вы посмотрите, что у вас за программа.startи поехал код! Здесь мы видим вызов метода createPane(). И этот метод createPane() создает пользовательский интерфейс в виде кода.

Код проекта:

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

Данный пример покажет вам, когда вы сделаете данный пример, что все, что можно сделать с помощью кода, именно относительно иерархии объектов и их настройки, все это можно сделать с помощью FXML. Конечно, в коде существует возможность иногда сделать как-то очень компактно.

Допустим я могу запустить цикл, который сделает 100 итераций и добавит в дерево объектов 100 новых элементов. Ну понятно, что цикл запустить в FXMLвы не сможете. Тогда может быть придется делать какой-то комбинированный интерфейс. Понимаете, да? Часть в FXML, а какая-то часть программная. Это вполне разумный вариант. Но здесь мы должны все сделать в FXMLи будет паттерн MVC.

Ответы:

Результат:

JavaFX Scene Builder

Подобные файлы, которые мы сделали в лабе – это правильно. Хотя бы один раз посмотреть, понять, попробовать. Но правильные проекты лучше писать в XMLлучше какие-то средства генерации кода. Это же все-таки дизайн. Поэтому должно быть визуальное проектирование. Есть такое и это SceneBuilder. Никаких проблем. Качается отдельно бесплатно с сайта Oracle. Устанавливаете и вперед.

Добавление функционала JavaFXв Swingприложение

http://docs.oracle.com/javafx/2/swing/jfxpub-swing.htm

Хорошо… сдвигаемся чуть-чуть вперед. Несколько слайдов для общего развития. Тем более там в начале было взаимодействие со Swing. Есть такое ощущение, что у них вышла новая версия, а эту упростили.

У нас программа Swing. Я хочу в нее добавить что-то из JavaFX. Вы скажете: «что там есть такого интересного в JavaFX?». А мы не видели еще этого – графики! Там есть готовые графики. Представьте, как это не просто красиво нарисовать графики на экране. Кто-нибудь пытался решать эту задачу когда-нибудь руками? Я помню в детстве пытался сделать красиво, чтобы это было по сечению распределение температуры. А потом когда я уволился, появились современные библиотеки с градиентной заливкой. Там делать ничего не надо! Задал все что нужно, и у тебя все залилось. Поэтому берете готовый класс. Мы все увидим. Картинку откроем, посмотрите, какие графики строятся. Просто данные дайте и вам построят графики. Но это и можно включить в Swing. Там таких замечательных графиков нет. Но Swing – это другая библиотека. Поэтому контейнер так и называется JFXPanel. Раз первая буква «J»– значит Swing. И самое неприятное – это последняя позиция. Они в разных потоках работают. Если вы собираетесь обращаться к функционалу, которое вы добавили в этот Panel – это же у нас JavaFXв этом Panel. Так к нему нужно обращаться через свой поток. В Swingу нас был eventQueue, а здесь Platform. runLater ну и так далее. Если вы вот этот код в Swingнаберете, то вызов метода (какой-то там initfxScene) произойдет в правильном потоке для JavaFX.

Добавление функционала Swing в JavaFX приложение

https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/title.htm#top

Все это возможно и в обратную сторону. Я в JavaFXдобавляю (а в JavaFXкаждый элемент в дереве называется «узел - node») – SwingNode.

Соответственно, SwingNode – это часть JavaFX, но в него можно поставить элемент из библиотеки Swing. И точно такая же проблема с переключением потоков. Все точно также. Но тут есть класс-обертка (когда мы там генерировали код в Swing – eventQueue) SwingUtilities. Это тот же самый eventQueue. Не помню – сказал я или нет, но JavaFXпроверяет какой поток обращается к элементу управления. Если неправильный поток, то Exception. Это нормально и правильно.

Возьмем SceneControl. Ну основы-то не изменились. Вот у нас классы. Допустим тот же самый Button, который мы с вами видели.label, control, nodeи т.д. Достаточно большая иерархия. Обратите внимание, что вершина иерархии всех элементов, которые в JavaFX–это node. Вот это их суперкласс. Наверно, где-то на уровне этого класса в nodeи проверяется правильность потоков, т.е. если не тот поток, а мы знаем какой должен быть. Значит nodeможет где-то в любой момент проверить и если он видит неправильный поток (один из суперклассов), то он выдает Exception. Это важно. Вот такую простейшую ошибку вы не допустите, как в Swing.

Коллекции JavaFX.

Еще пришлось авторам-разработчикам пришлось поработать для JavaFX. А именно, коллекции пришлось новые создать. Вы скажете: «простите, ну сколько можно?!». У нас были старые, новые (которые не потокобезопасные), потом новые (потокобезопасные), а теперь коллекции для JavaFX. Вы спросите: «а эти чем отличаются? они потокобезопасные?». Нет, зачем? они не потокобезопасные. Тогда чем они лучше тех, что у нас были в первом курсе (List, Map,Set…)?А тут понимаете, с теми коллекциями есть проблемы. Ведь как работает современная технология в пользовательском интерфейсе? Вот представьте. У вас где-то изменились данные. Вопрос: на экране это должно обновиться? Как те, кто отвечают за обновление экрана узнают, что данные изменились? А! Вы будете им все время подсказывать? Вы будете мониторить данные и если они изменились, то вы будете кого-то пинать и говорить: «перерисуй все на экране». Ну да. Мы так и программировали в прошлом веке. А сегодня коллекция должна сообщать. Она должна иметь возможность, чтобы вы подписались на информацию об изменении. Вот эти коллекции, которые в JavaFX, они в себе и содержат самое важное отличие. Возможность подписки на изменения. На самом деле это не самостоятельные коллекции. Там даже где-то слово «обертка» написана. Т.е. у меня может быть обычный List, а может быть вот этот: FXCollections. observableList. И что это за зверь? Он умеет сообщать об изменениях и вы можете подписаться. Показано два варианта, как можно подписываться. Первый вариант: addListener – старинный. Второй вариант: тоже addListener поновее.

Вопрос: В чем разница?

Ответ:

Первый – версия 1.0, т.е. самая старинная версия, что есть в библиотеке. Это было всегда, еще при существовании AWT. Но этот вариант очень информативен, где вы должны использовать интерфейс InvalidationListener. Почему? А он просто вам говорит: «изменилось». Всё. Т.е. сообщение о том, что изменилось. А что конкретно? А какие элементы добавились? А может быть кто-то убавился? Вот это здесь непонятно. Но это годится для того случая, если вам нужно просто все перерисовать на экране. Какая разница! Ну изменилось, все перерисовали. Замечательно!

Второй – вариант с уточнением. Здесь другой новый интерфейс. ИондажеGeneric. ListChangeListener. Во как! И соответственно из этого объекта, которое вам сюда когда произойдет событие кинут, вы можете получить список изменений, список удалений, список добавлений и т.д. И это получается, если вы хотите обновить только то, что изменилось. Вот где-то был такой вопрос: а можно обновить только правый левый угол, если у меня изменилась какая-то инфомация? Да. Вот если вы сделаете ваши данные в виде какой-то такой информативной коллекции, то, конечно, можно. Все это, естественно, каждый раз писать руками бы очень не хотелось, поэтому они создали такие классы начинающиеся на FXCollections и т.д. Это нам подсказка, что это как раз сделано для библиотеки. А в библиотеке JavaFXс другой стороны есть возможность сделать «DataBinding – привязка данных». Слышали про это? В JavaFXеще существует технология привязки данных. Если коллекция может сообщить, то пользовательский интерфейс как раз может выступать в качестве получателя этих событий и будет перерисовывать. В общем здесь есть возможность что-то сделать покрасивее.

На этом слайде я создал полный готовый пример. Если у вас есть желание потыкать и попробовать разные варианты. Кстати, забыл сказать! Вы не обязаны пользоваться этими классами-коллекциями только в JavaFX! Вы в любом приложении Javaможете их брать, т.к. это часть JDK.

import java.util.ArrayList; import javafx.beans.*; import javafx.collections.*;   class Box{ public int a,b; public Box(int a, int b) {    this.a = a;    this.b = b; } public String toString() {    return a+" "+b; } } public class JavaApplication6 {   public static void main(String[] args) {    ArrayList<Box> list=new ArrayList<>();    list.add(new Box(1,2));    list.add(new Box(2,3));      ObservableList<Box> olist=FXCollections.observableArrayList(list);    list.add(new Box(3,4));    list.get(0).a=7;      if (list.get(0)==olist.get(0)) System.out.println("=="); //yes ==      olist.addListener(new InvalidationListener() {        public void invalidated(Observable obs) {            System.out.println("invalidate!");    }});      olist.addListener(new ListChangeListener<Box>() {        public void onChanged(ListChangeListener.Change<? extends Box> ch) {            System.out.println(ch.getList());    }});      olist.add(new Box(7,9));      for(Box s: list) System.out.println(s);    System.out.println();    for(Box s: olist) System.out.println(s); } }

 

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

· Копия списка – у вас есть в списке 5 ссылок. Копия – это будет 5 ссылок, т.е. еще одна коллекция с пятью ссылками. И получается, что 2 коллекции теперь раздельно. Если я в ту старую первую коллекцию добавлю какой-то элемент, то простите. Копия про это ничего не знает. Понимаете, да? Это разные коллекции по сути.

· Обертка –у вас есть коллекция, и вы ее как бы оборачиваете в некий функционал. Если вы в старую коллекцию добавляете, ну какая разница. Это одна и та же коллекция и никакие копии не создаются. И если вы ее меняете (хотите старую меняйте, хотите через обертку меняйте), все-равно все они ссылаются на события «изменен»

Поэтому вам решать. Хотите копию создать или хотите создать просто некую обертку, чтобы получить дополнительную возможность, а именно «информацию об изменении».


Поделиться с друзьями:

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

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...

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

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.02 с.