Омский государственный университет путей сообщения
Кафедра «Автоматика и системы управления»
К ЗАЩИТЕ ДОПУСТИТЬ
Доцент кафедры АиСУ
________
Разработка приложения на платформе java
Пояснительная записка к курсовой работе
по дисциплине «Объектно-ориентированное программирование»
ИНМВ.401000.000 ПЗ
Студент гр. 25З
___________
«__»________2017 г.
Руководитель – доцент
кафедры «АиСУ»
___________
«__»________2017 г.
Омск 2017
Задание
Необходимо создать приложение небольшого хостела, которое будет решать следующие задачи:
– вывод информации о клиентах;
– заселение /выселение постояльца;
– сохранение данных в формате XML;
– печать списка гостей;
– печать индивидуального чека;
– редактирование данных постояльца.
Реферат
УДК 681.3.06
Пояснительная записка к курсовой работе содержит 23 страницы, 8 рисунков, 5 использованных источников, 2 приложения с листингами и скринами программы.
Объектом курсовой работы является проектирование приложения.
Цель курсовой работы – предоставить удобный и быстрый доступ к приложению, содержащих информацию гостинице.
Результатом курсовой работы является приложение «Хостел».
Пояснительная записка выполнена в текстовом редакторе MicrosoftWord 2015.
Содержание
Задание 2
Реферат 3
Введение 5
1 Среда разработки и библиотеки 6
2 Структура проекта 7
3 Создание приложения 8
3.1 Главное окно 8
3.2 Окно редактирования персональных данных 10
Заключение 12
Список использованной литературы 13
Приложение А 14
Приложение Б 22
Введение
JavaFX – платформа для создания приложений с насыщенным графи-ческим интерфейсом, постепенно пришедшая на замену Swing. Она позволяет грамотно отделять бизнес-логику от графического интерфейса, взаимодействующего с пользователем. Можно как создавать окна с помощью SceneBuilder (используется декларативный язык описания FXML), так и в старом стиле, вручную настраивая и устанавливая компоненты. Библиотека JavaFX подключена к JDK начиная с восьмой версии.
Целью данного проекта является освоение современного фреймворка, за-крепление новыков программирования в объектно-ориентированном стиле, ознакомление и взаимодействие с языком разметки XML.
1 Среда разработки и библиотеки
JavaFX – платформа на основе Java для создания приложений с насы-щенным графическим интерфейсом. Предназначена для создания десктопных и мобильных приложений. Приложения JavaFX создаются с помощью декларативного языка программирования JavaFX Script. Для разработки приложений на языке JavaFX Script необходимо установить JavaFX SDK, который входит в поставку с Java SE 7. Из кода, написанного на языке JavaFX Script, можно обращаться к любым библиотекам Java. Поэтому совместное использование языков Java и JavaFX Script позволяет решать разнообразные задачи, например, логика бизнес-приложения может быть написана на Java, а графический интерфейс пользователя – на JavaFX Script. Версия JavaFX 8 предоставляет возможность 3D-графики, сенсорного ввода, а также поддержку печати.
Разработка приложения производилась в IDE IntelliJ IDEA, созданная рос-сийскими разработчиками среде, обладающей большим количеством воз-можностей, в том числе и для взаимодействия с FXML-файлом и SceneBuilder.
Использовались библиотека JDOM для последовательного считывания из XML-файла, JAXB для маршаллинга и анмаршаллинга объектов.
2 Структура проекта
О клиенте должно храниться 5 характеристик, оформленных в таблице:
– ФИО;
– номер паспорта;
– количество дней;
– номер;
– цена за номер.
Пакет view содержит следующие классы:
- MainClientController – класс, содержащий методы обработки действий пользователя:
- EditWinController –класс, отвечающий за обработку событий действий над записью:
Также в пакете view находятся два fxml-файла для двух окон приложения. Главное окно будет запускаться непосредственно при запуске программы, в нем будет осуществляется взаимодействие пользователя с программой. Параметры окна указывается в файле «mainWin. fxml». Вид главного окна представлен на рисунке 1. Окно редактирования данных (рисунок 2) появляется после запроса на персонализацию данных. Листинги файлов представлены в приложении.

Рисунок 1 – Главное окно приложения

Рисунок 2 – Окно редактирования данных
3 Создание приложения
3.1 Главное окно
Для запуска приложения в классе Main содержатся тестовые данные, записанные в методе testInit. После загрузки файла mainwin. fxml в таблице появляются четыре записи (рисунок 3).

Рисунок 3 – Тестовые данные
Для заселения нового постояльца необходимо заполнить поля в верхнем левом углу главного окна. При нажатии кнопки вызывается метод handleAdd2, который к клиентскому листу добавляет еще одну запись. Данные берутся из полей TextField, заполненных вручную. Для полей «паспорт», «дни» и «цена» используются парсеры parseInt и parseFloat, преобразующие введенные данные с объекты целого и вещественно типа соответственно. При неверном заполнении в TextArea «Итог действий» будет записано сообщение об ошибке, а при полном соответствии данных будет добавлена новая запись и сообщение об успешном завершении действия (рисунки 4-5). Сообщения об ошибках выставляются автоматически, вручную записать в TextArea «Итог действий» ничего нельзя.

Рисунок 4 – Ошибка добавления клиента

Рисунок 4 – Заселение клиента
Аналогичная обработка ошибок реализованная для методов удаления, сохранения, загрузки и печати.
3.2 Окно редактирования персональных данных
Для персонализованных данных загружается отдельное окно на рисунке 5. Все поля в нем доступны для редактирования. Новые данные отображаются на месте старой записи.
Для выставления счета реализован отдельный метод печати чека. Выходными данными является PDF файл, содержащий информацию об одном клиенте(рисунок 7). Так же реализован метод печати для всех гостей (рисунок 8).

Рисунок 5 – Редактирование данных клиента

Рисунок 6 – Сохранение изменений

Рисунок 7 – Персональный чек

Рисунок 8 – Общая печать
Заключение
В процессе выполнения курсовой работы было создано приложение «Хостел», которое выполняет следующие задачи:
– вывод информации о клиентах;
– заселение /выселение постояльца;
– сохранение данных в формате XML;
– печать списка гостей;
– печать индивидуального чека;
– редактирование данных постояльца.
Библиографический список
1 Разработка приложений на платформе JavaFX/ ,
2 Using JavaFX UI Controls [Электронный ресурс] / Режим доступа: http://docs. /javafx/2/ui_controls/jfxpub-ui_controls. htm
3 Populate a tableview using database in JavaFX [Электронный ресурс] / Режим доступа: https:///questions/18497699/populate-a-tableview-using-database-in-javafx
4 Database Operations in JavaFX [Электронный ресурс] / Режим доступа: http://www. /database-operations-javafx/
5 СТП ОмГУПС–1.2–2005
Приложение А
(обязательное)
Листинг программы
Класс MainClientController.
package view;
public class MainClientController {
Stage primaryStage;
ObservableList<Client> clientList;
@FXML
TableView<Client> table;
@FXML
TextField FIO_add;
@FXML
TextField pas_add;
@FXML
TextField day_add;
@FXML
TextField room_add;
@FXML
TextField pr_add;
@FXML
TextArea rez;
@FXML
TableColumn<Client, String> FIOColumn;
@FXML
TableColumn<Client, Number> pasColumn;
@FXML
TableColumn<Client, Number> dayColumn;
@FXML
TableColumn<Client, String> numColumn;
@FXML
TableColumn<Client, Number> priceColumn;
ObservableList<Room> roomList;
private Stage dialogStage ;
@FXML
private void handleChange(){
try{
FXMLLoader loader = new FXMLLoader();
loader. setLocation(getClass().getResource("editWin. fxml"));
Pane page = loader. load();
dialogStage = new Stage();
dialogStage. setTitle("Редактирование данных");
dialogStage. initModality(Modality. WINDOW_MODAL);
dialogStage. initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage. setScene(scene);
rez. setText("Запись готова для редактирования.");
EditWinController controller = loader. getController();
int editingIndex = table. getSelectionModel().getFocusedIndex();
controller. initt(clientList, editingIndex, this, roomList);
dialogStage. showAndWait();
} catch (IOException e){
e. printStackTrace();
rez. setText("Произошла ошибка: загрузка не выполнена.");
}
}public void close(){dialogStage. close();
rez. setText("Редактирование завершено");}
Листинг А1 – Класс MainClientController, лист 1
public void init(ObservableList<Client> clientList, ObservableList<Room> categoryList, Stage primaryStage){
this. primaryStage = primaryStage;
this. clientList = clientList;
roomList = categoryList;
table. setItems(clientList);
FIOColumn. setCellValueFactory(cellData -> cellData. getValue().FIOProperty());
pasColumn. setCellValueFactory(cellData -> cellData. getValue().pasProperty());
dayColumn. setCellValueFactory(cellData -> cellData. getValue().DayProperty());
numColumn. setCellValueFactory(cellData -> cellData. getValue().NumProperty());
priceColumn. setCellValueFactory(cellData -> cellData. getValue().priceProperty());
priceColumn. setCellFactory(cellData -> new PriceCell(clientList));
}
@FXML
private void handleSave(){
ClientXML xml = new ClientXML(clientList);
try {
JAXBContext context = JAXBContext. newInstance(ClientXML. class);
Marshaller m = context. createMarshaller();
m. setProperty(Marshaller. JAXB_FORMATTED_OUTPUT, true);
m. marshal(xml, new File("saveFile. xml"));
rez. setText("Данные успешно сохранены");
} catch (Exception e) { e. printStackTrace();
rez. setText("Произошла ошибка: сохранение не выполнено. Проверьте наличие файла");}
}
@FXML
private void handleLoad(){
try {
JAXBContext context = JAXBContext. newInstance(ClientXML. class);
Unmarshaller um = context. createUnmarshaller();
ClientXML xml = (ClientXML) um. unmarshal(new File("loadFile. xml"));
clientList. clear();
clientList. addAll(xml. getList());
rez. setText("Данные успешно загружены");
} catch (Exception e) { e. printStackTrace();
rez. setText("Загрузка не выполнена. Проверьте наличие файла");}
}
@FXML
private void handleAdd2(){
try{
String a = FIO_add. getText();
Integer b = Integer. parseInt(pas_add. getText());
Integer c = Integer. parseInt(day_add. getText());
String d = room_add. getText();
Float e = Float. parseFloat(pr_add. getText());
clientList. add(new Client(a, b, c, d, e));
rez. setText("Новый клиент добавлен");
}
catch (Exception e){
e. printStackTrace();
rez. setText("Новый клиент не добавлен. Возможно, вы заполнили не все поля. Попробуйте еще раз");
}
Листинг А1, лист 2
@FXML
private void handleDel() {
try{
if (table. isFocusTraversable()) {
int index = table. getSelectionModel().getSelectedIndex();
clientList. remove(clientList. get(index));
rez. setText("Данные клиента успешно удалены");
}
}
catch (Exception e){
e. printStackTrace();
rez. setText("Не удалось выселить клиента. Выберите нужную запись и попробуйте еще раз");
}
}
@FXML
private void handlePrint(){
try {
PrinterJob job = PrinterJob. createPrinterJob();
Printer printer = job. getPrinter();
PageLayout pageLayout = printer. getDefaultPageLayout();
PageLayout newpageLayout = printer. createPageLayout(pageLayout. getPaper(), PageOrientation. REVERSE_LANDSCAPE, Printer. MarginType. DEFAULT);
TableView g = new TableView();
g. setItems(clientList);
g. getColumns().addAll(FIOColumn, pasColumn, dayColumn, numColumn, priceColumn);
VBox t = new VBox();
Label cat = new Label("Список гостей");
t. getChildren().addAll(cat, g);
if (job!= null)
if (job. printPage(newpageLayout, t))
job. endJob();
rez. setText("Документ для печати готов");
}
catch (Exception e){
e. printStackTrace();
rez. setText("Не удалось отправить на печать. Попробуйте еще раз");
}
}
}
Листинг А1, лист 3
Класс EditWinController.
package view;
public class EditWinController {
ObservableList<Client> clientList;
int editingIndex;
@FXML
TextField FIO;
@FXML
FloatField pas;
@FXML
FloatField day;
@FXML
FloatField price;
@FXML
ComboBox room;
@FXML
TextArea rez2;
@FXML
Label itog;
private MainClientController controller;
@FXML
public void save_edit(){
try {
Client cl = new Client(FIO. getText(), Integer. parseInt(pas. getText()), Integer. parseInt(day. getText()), room. getValue().toString(), Float. parseFloat(price. getText()));
clientList. set(editingIndex, cl);
rez2.setText("Изменения сохранены.");
}
catch (Exception a)
{
a. printStackTrace();
rez2.setText("Изменения не сохранены. Проверьте все ли поля заполнены и попробуйте еще раз.");
}
}
@FXML
public void cancel(){controller. close();
rez2.setText("Изменения отменены");}
@FXML
public void cl(){controller. close();
rez2.setText("Редактирование завершено");}
public void initt(ObservableList<Client> clientList, int editingIndex, MainClientController controller, ObservableList<Room>roomList)
{
this. controller = controller;
this. clientList = clientList;
this. editingIndex = editingIndex;
Client cl = clientList. get(editingIndex);
FIO. setText(cl. getFIO());
pas. setText(new Integer(cl. getPas()).toString());
day. setText(new Integer(cl. getDay()).toString());
room. setItems(roomList);
price. setText(new Float(cl. getPrice()).toString());
ch();
}
public void ch(){
float all = 0;
Float a = Float. parseFloat(day. getText());
Float b = Float. parseFloat(price. getText());
Листинг А2 – Класс EditWinController, лист 1
all=a*b;
itog. setText("Счёт: "+ all + " руб.");
}
@FXML
private void handlePrint_pers(){
try{
PrinterJob job = PrinterJob. createPrinterJob();
Printer printer = job. getPrinter();
PageLayout pageLayout = printer. getDefaultPageLayout();
PageLayout newpageLayout = printer. createPageLayout(pageLayout. getPaper(), PageOrientation. PORTRAIT, Printer. MarginType. DEFAULT);
String a = FIO. getText();
String b = pas. getText();
String c = day. getText();
String e = price. getText();
VBox t = new VBox();
Label title = new Label("Персональный чек");
title. setFont(Font. font(30));
Label a1 = new Label("ФИО клиента: "+a);
Label b1 = new Label("Паспортные данные: "+b);
Label c1 = new Label("Количество дней: "+c);
Label e1 = new Label("Цена: "+e);
t. getChildren().addAll(title, a1,b1,c1,e1, itog);
if (job!= null)
if (job. printPage(newpageLayout, t))
job. endJob();
rez2.setText("Чек для печати готов");
}
catch (Exception e){
e. printStackTrace();
rez2.setText("Не удалось отправить на печать. Попробуйте еще раз");
}
}
}
public class WorkPlan extends Application {
public static final Logger logger = LogManager. getLogger("WorkPlan");
public static File xmlFile;
public static Map Plans = new HashMap< String, Plan>();
public static LearnPlan learnPlan=new LearnPlan();
@Override
public void start(Stage primaryStage) throws Exception {
MainWinController. setPlans(Plans);
MainWinController. setLearnPlan(learnPlan);
FXMLLoader loader = new FXMLLoader();
loader. setLocation(getClass().getResource("/view/main/mainWin. fxml"));
Parent root = loader. load();
primaryStage. setTitle("WorkPlan");
primaryStage. setScene(new Scene(root));
primaryStage. show();
}
public static void main(String[] args) {
launch(args);
}
}
Листинг А2, лист 2
FXML файл mainWin
<?xml version="1.0" encoding="UTF-8"?>
<AnchorPane prefHeight="400.0" prefWidth="760.0" xmlns="http:///javafx/8.0.112" xmlns:fx="http:///fxml/1" fx:controller="view. MainClientController">
<children>
<TextArea fx:id="rez" editable="false" layoutX="380.0" layoutY="340.0" prefHeight="40.0" prefWidth="365.0" promptText="Здесь будут отображаться результат действий или сообщения об ошибках" wrapText="true" />
<Label layoutX="250.0" layoutY="340.0" prefHeight="37.0" prefWidth="120.0" text="Итог действия">
<font>
<Font name="System Bold" size="12.0" />
</font></Label>
<VBox layoutX="60.0" layoutY="24.0" spacing="5.0">
<children>
<TextField fx:id="FIO_add"prefHeight="25.0" prefWidth="173.0" promptText="ФИО" />
<TextFieldfx:id="pas_add"prefHeight="25.0"prefWidth="79.0"promptText="Паспорт" />
<TextField fx:id="day_add"prefHeight="25.0"prefWidth="79.0" promptText="Номер" />
<TextField fx:id="room_add"prefHeight="25.0"prefWidth="79.0" promptText="Дни" />
<FloatField fx:id="pr_add" prefHeight="25.0"prefWidth="120.0"promptText="Цена" />
</children>
</VBox>
<Separator layoutX="240.0" layoutY="0"orientation="VERTICAL" prefHeight="400.0"/>
<TableView fx:id="table"editable="true" layoutX="250.0"prefHeight="294.0" prefWidth="500.0">
<columns>
<TableColumn fx:id="FIOColumn" prefWidth="180.0" text="ФИО" />
<TableColumn fx:id="pasColumn" prefWidth="120.0" text="Паспорт" />
<TableColumn fx:id="dayColumn" prefWidth="60.0" text="Дни" />
<TableColumn fx:id="numColumn" prefWidth="60.0" text="Номер" />
<TableColumn fx:id="priceColumn" prefWidth="80.0" text="Цена" />
</columns>
</TableView>
<Separator layoutX="0"layoutY="210.0"orientation="HORIZONTAL"prefWidth="243.0" />
<Button fx:id="addEmpBtn" layoutX="9.0" layoutY="180.0" mnemonicParsing="false" onAction="#handleAdd2" prefHeight="25.0" prefWidth="224.0" text="Заселить нового гостя" />
<VBox layoutX="9.0" layoutY="220" prefHeight="130.0" prefWidth="224.0" spacing="10.0">
<children>
<Button layoutX="175.0" layoutY="24.0"mnemonicParsing="false" onAction="#handleDelprefHeight="25.0 prefWidth="224.0" text="Выселить постояльца" />
<Button layoutX="261.0" layoutY="24.0" mnemonicParsing="false" onAction="#handleChange" prefHeight="25.0" prefWidth="224.0" text="Персонализация данных" />
<Button layoutX="334.0" layoutY="24.0" mnemonicParsing="false" onAction="#handleLoad" prefHeight="25.0" prefWidth="224.0" text="Загрузить данные" />
<Button layoutX="261.0" layoutY="24.0" mnemonicParsing="false" onAction="#handleSave" prefHeight="25.0" prefWidth="224.0" text="Сохранить данные" />
<Button fx:id="searchEmpsBtn" layoutX="411.0" layoutY="24.0" mnemonicParsing="false" onAction="#handlePrint" prefHeight="25.0" prefWidth="224.0" text="Вывести на печать" />
</children>
</VBox>
</children>
</AnchorPane>
Листинг А3 – FXML файл mainWin
FXML файл editWin
<?xml version="1.0" encoding="UTF-8"?>
<AnchorPane prefHeight="300.0" prefWidth="320.0" xmlns="http:///javafx/8.0.112" xmlns:fx="http:///fxml/1" fx:controller="view. EditWinController">
<TextArea fx:id="rez2" editable="false" layoutX="4.0" layoutY="260.0" prefHeight="30.0" prefWidth="280.0" promptText="Здесь будут отображаться результат действий или сообщения об ошибках" wrapText="true" />
<Button layoutX="150.0" layoutY="210.0" mnemonicParsing="false" onAction="#handlePrint_pers" prefHeight="25.0" prefWidth="74.0" text="Печать" />
<Button layoutX="250.0" layoutY="210.0" mnemonicParsing="false" onAction="#cl" prefHeight="25.0" prefWidth="74.0" text="Выход" />
<Label fx:id="itog" layoutX="4.0" layoutY="210.0" prefHeight="35.0" prefWidth="120.0" text="Счёт: ">
<font>
<Font name="System Bold" size="12.0" />
</font></Label>
<Label layoutX="4.0" layoutY="230.0" prefHeight="35.0" prefWidth="100.0" text="Итог действия:">
<font>
<Font name="System Bold" size="12.0" />
</font></Label>
<GridPane layoutX="10.0" prefHeight="200.0" prefWidth="320.0">
<columnConstraints>
<ColumnConstraints prefWidth="85.0" />
<ColumnConstraints prefWidth="220.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints prefHeight="38.0" />
<RowConstraints prefHeight="38.0" />
<RowConstraints prefHeight="38.0" />
<RowConstraints prefHeight="38.0" />
<RowConstraints prefHeight="38.0" />
<RowConstraints prefHeight="38.0" valignment="CENTER" />
</rowConstraints>
<children>
<Label text="ФИО" />
<Label text="Паспорт" GridPane. rowIndex="1" />
<Label text="Дни" GridPane. rowIndex="2" />
<Label text="Номер" GridPane. rowIndex="3" />
<Label text="Цена" GridPane. rowIndex="4" />
<TextField fx:id="FIO" prefHeight="7.0" prefWidth="90.0" GridPane. columnIndex="1" />
<FloatField fx:id="pas" GridPane. columnIndex="1" GridPane. rowIndex="1" />
<FloatField fx:id="day" GridPane. columnIndex="1" GridPane. rowIndex="2" />
<FloatField fx:id="price" GridPane. columnIndex="1" GridPane. rowIndex="4" />
<ComboBox fx:id="room" prefHeight="25.0" prefWidth="105.0" GridPane. columnIndex="1" GridPane. rowIndex="3" />
<Button mnemonicParsing="false" onAction="#save_edit" text="Сохранить" GridPane. rowIndex="5" />
<Button mnemonicParsing="false" onAction="#cancel" prefHeight="25.0" prefWidth="74.0" text="Отменить" GridPane. columnIndex="1" GridPane. rowIndex="5" />
</children>
</GridPane>
</AnchorPane>
Листинг А4 – Файл editWin
Класс Client
package model;
@XmlType(propOrder = {"FIO", "pas", "day","num", "price"})
public class Client {
StringProperty FIO = new SimpleStringProperty("");
IntegerProperty pas = new SimpleIntegerProperty(0);
IntegerProperty day = new SimpleIntegerProperty(0);
StringProperty num = new SimpleStringProperty("");
FloatProperty price = new SimpleFloatProperty(0);
public Client(){}
public Client(String FIO, Integer pas, Integer day, String num, Float price) {
this. FIO = new SimpleStringProperty(FIO);
this. pas = new SimpleIntegerProperty(pas);
this. day = new SimpleIntegerProperty(day);
this. num = new SimpleStringProperty(num);
}
@XmlElement(name = "ФИО")
public String getFIO() { return FIO. get(); }
public StringProperty FIOProperty() {
return FIO;
public void setFIO(String FIO) {
this. FIO. set(FIO);
@XmlElement (name = "Паспорт")
public int getPas() {
return pas. get();
public IntegerProperty pasProperty() {
return pas;
}
public void setPas(int pas) {
this. pas. set(pas);
}
@XmlElement (name = "Дни")
public int getDay() {
return day. get();
}
public IntegerProperty DayProperty() {
return day;}
public void setDay(int day) {
this. day. set(day);
}
@XmlElement (name = "Номер")
public String getNum() {
return num. get();
}
public StringProperty NumProperty() {
return num;
}
public void setNum(String num) {
this. num. set(num);
}
@XmlElement (name = "Цена")
public float getPrice() {
return price. get();
}
public FloatProperty priceProperty() {
return price;
}
public void setPrice(float price) {
this. price. set(price);
} }
Листинг А5 – Класс Client
Приложение Б
(обязательное)
Скрины работы программы

Рисунок Б1 – Заселение клиента в главном окне

Рисунок Б2 – Редактирование данных клиента

Рисунок Б3 – Персональный чек

Рисунок Б4 – Общая печать

Рисунок Б5 – Выселение постояльца

Рисунок Б6 – Загрузка из XML файла

Рисунок Б7 – Сохранение в XML файл


