Розробка

Віконце з кнопками на JavaFX:

Привіт!

Мої знання у створенні якогось графічного інтерфейсу до недавніх пір були нульовими. Тому було прийнято рішення трохи полазити простори Інтернету і створити якесь віконце з якими-небудь кнопками, за допомогою яких буде щось відбуватися. Можливо, в цьому тексті хтось знайде відповіді на виниклі коли питання; в той же час я сподіваюся на серйозну і грамотну критику.

Що буде відбуватися?

Так як мета у мене — розібратися з JavaFX, потрібно придумати якусь функцію у нашого вікна. Ідея така: створимо набір людей (припустимо, що вони працюють в якійсь компанії), для кожного з яких буде відомо ім’я, вік, зарплата і сімейний стан. Наше вікно, по-перше, буде виводити інформацію про кожного з них, по-друге, змінювати зарплату будь-якого співробітника, по-третє, мати можливість додавати нового співробітника, і, нарешті, в-четверных, здатний фільтрувати працівників в залежності від їх значень атрибутів. У результаті повинно вийти щось на зразок цього:

Починаємо

Насамперед створюємо головний клас Company, звідки відбуватиметься запуск додатка:

package company;

public class Company {

 public static void main(String[] args) {


}

}

В цьому класі будемо розширювати можливості класу Application. З нього нам потрібен головним чином метод start(), в якому відбуватиметься основна дія (будемо пропускати помилки, що виникають в цьому методі; іншими словами, якщо щось піде не так, наше вікно не закриється, але в консолі з’явиться StackTrace помилки):

package company;

import javafx.application.Application;
import javafx.stage.Stage;

public class Company extends Application {

 public void start(Stage primaryStage) throws Exception {

}

 public static void main(String[] args) {
launch(args);
}

}

Відмінно. Для того, щоб працювати з представниками співробітників компанії, створимо клас User: об’єкти цього класу та будуть виступати в ролі співробітників.

Клас User

package company;

public class User {

 User(String name, int age, int salary, boolean married) {
 this.name = name;
 this.age = age;
 this.salary = salary;
 this.married = married;
}

 public void changeSalary(int x) {
 salary = (salary + x <= 0)? 0: salary + x;
}

 public String toString() {
 return name;
}

 public String getAge() {
 return String.valueOf(age);
}

 public String getSalary() {
 return String.valueOf(salary);
}
 public String getMarried() {
 return (married)? ("married"):("single");
}

 String name;
 int age;
 int salary;
 boolean married;
}

Створюємо

Поки при запуску програма у нас не відбувається нічого. Щоб з’явилося хоча б віконечко, його необхідно додати. Це і зробимо.

package company;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Company extends Application {

 public void start(Stage primaryStage) throws Exception {
 Scene scene = new Scene(root, WIDTH, HEIGHT);
primaryStage.setTitle("Company");
primaryStage.setScene(scene);
primaryStage.show();
}

 public static void main(String[] args) {
launch(args);
}

 Group root = new Group();

 final private int WIDTH = 1000;
 final private int HEIGHT = 600;

}

Що ми тільки що зробили: ми додали сцену (scene) розміром , дали їй назву «Company». На нашій сцені присутній група root, яка за своєю суттю є «контейнером», який буде містити в собі всі кнопки.

Додамо випадаючий список з нашими співробітниками. Створимо HBox, який покладемо наш випадаючий список ComboBox userBox і кнопку, яка буде видавати інформацію про співробітника (сам HBox помістимо в VBox):

package company;

import java.util.ArrayList;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Company extends Application {

 public void start(Stage primaryStage) throws Exception {

 users.add(new User("Alice", 20, 150, false));
 users.add(new User("Bob", 34, 300, true));
 users.add(new User("Peter", 18, 100, 'false'));
 users.add(new User("Kate", 38, 300, true));
 users.add(new User("Steve", 31, 250, true));
 users.add(new User("Alan", 62, 500, true));
 users.add(new User("Julia", 33, 320, true));
 users.add(new User("Patric", 37, 300, true));
 users.add(new User("Alexander", 34, 280, true));
 users.add(new User("George", 28, 180, true));
 users.add(new User("Mary", 22, 190, false));

userBox.getItems().addAll(users);

root.getChildren().add(strings);

 strings.setPadding(new Insets(10, 30, 10, 30));
strings.setSpacing(20);

 strings.getChildren().add(new Text("Select the user"));
strings.getChildren().add(buttonBox);

buttonBox.setSpacing(10);
buttonBox.getChildren().add(userBox);

 Scene scene = new Scene(root, WIDTH, HEIGHT);
primaryStage.setTitle("Company");
primaryStage.setScene(scene);
primaryStage.show();
}

 public static void main(String[] args) {
launch(args);
}

 Group root = new Group();

 VBox strings = new VBox();

 HBox buttonBox = new HBox();

 ComboBox<User> userBox = new ComboBox<>();

 final private int WIDTH = 1000;
 final private int HEIGHT = 600;

 private ArrayList<User> users = new ArrayList<>();

}

Що таке VBox,HBox і ComboBox
HBox — це набір кнопок, текстів, полів для введення, кожен об’єкт якого розташований послідовно горизонтально. Аналогічний йому, VBox є тим же самим, але зберігає свої об’єкти (children) по вертикалі. Ми будемо використовувати наступну схему: создатим VBox, в який будемо класти кілька HBox’ів, кожен з яких покладемо послідовність кнопок та полів.

ComboBox — це сам просто випадаючий список.

Тепер ми хочемо створити команду, яка буде видавати інформацію про обраному співробітнику. Додамо саму кнопку (Button) і текстове поле (TextField), яке буде виводитися текст. Ці два об’єкти додамо в HBox:

package company;

/* */

public class Company extends Application {

 public void start(Stage primaryStage) throws Exception {

 /* */

buttonBox.setSpacing(10);
buttonBox.getChildren().add(userBox);
buttonBox.getChildren().add(buttonGetInfo);
buttonBox.getChildren().add(textInfo);

 /* */
}

 /* */

 Button buttonGetInfo = new Button("Info");
 Text textInfo = new Text();

 /* */

}

Але поки ця кнопка нічого не робить. Щоб вона щось робила, їй необхідно призначити дію:

buttonGetInfo.setOnAction(new EventHandler<ActionEvent>() {
@Override
 public void handle(ActionEvent e) {
 User u = (User) userBox.getSelectionModel().getSelectedItem();
 if (u != null) {
 textInfo.setText("Age is" + u.getAge() + ", " + 
 "Salary is" + u.getSalary() + ", " + 
 "Relationship:" + u.getMarried());
 } else {
 textInfo.setText("User not selected");
}
}
});

Подальші дії

Абсолютно аналогічним чином додаємо ще два HBox’а: у другому буде відбуватися зміна зарплати, в третьому — добавляние нового співробітника. В силу того, що логіка тут абсолютно та ж сама, пропустимо пояснення цих моментів і відразу покажемо результат:

Код

package company;

import java.util.ArrayList;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Company extends Application {

 public void start(Stage primaryStage) throws Exception {

 users.add(new User("Alice", 20, 150, false));
 users.add(new User("Bob", 34, 300, true));
 users.add(new User("Peter", 18, 100, 'false'));
 users.add(new User("Kate", 38, 300, true));
 users.add(new User("Steve", 31, 250, true));
 users.add(new User("Alan", 62, 500, true));
 users.add(new User("Julia", 33, 320, true));
 users.add(new User("Patric", 37, 300, true));
 users.add(new User("Alexander", 34, 280, true));
 users.add(new User("George", 28, 180, true));
 users.add(new User("Mary", 22, 190, false));

userBox.getItems().addAll(users);

root.getChildren().add(strings);

 strings.setPadding(new Insets(10, 30, 10, 30));
strings.setSpacing(20);

 strings.getChildren().add(new Text("Select the user"));
strings.getChildren().add(buttonBox);
 strings.getChildren().add(new Text("Change the salary"));
strings.getChildren().add(changeSalaryBox);
 strings.getChildren().add(new Text("Add new User"));
strings.getChildren().add(addUserBox);

buttonBox.setSpacing(10);
buttonBox.getChildren().add(userBox);
buttonBox.getChildren().add(buttonGetInfo);
buttonBox.getChildren().add(textInfo);

changeSalaryBox.setSpacing(10);
changeSalaryBox.getChildren().add(buttonChangeSalary);
changeSalaryBox.getChildren().add(howMuchChange);

addUserBox.setSpacing(10);
 addUserBox.getChildren().add(new Text("Name: "));
addUserBox.getChildren().add(name);
 addUserBox.getChildren().add(new Text("Age: "));
addUserBox.getChildren().add(age);
 addUserBox.getChildren().add(new Text("Salary: "));
addUserBox.getChildren().add(salary);
 addUserBox.getChildren().add(new Text("Married: "));
addUserBox.getChildren().add(married);
addUserBox.getChildren().add(buttonAddUser);

 buttonGetInfo.setOnAction(new EventHandler<ActionEvent>() {
@Override
 public void handle(ActionEvent e) {
 User u = (User) userBox.getSelectionModel().getSelectedItem();
 if (u != null) {
 textInfo.setText("Age is" + u.getAge() + ", " + 
 "Salary is" + u.getSalary() + ", " + 
 "Relationship:" + u.getMarried());
 } else {
 textInfo.setText("User not selected");
}
}
 }); 

 buttonChangeSalary.setOnAction(new EventHandler<ActionEvent>() {
@Override
 public void handle(ActionEvent e) {

 User u = (User) userBox.getSelectionModel().getSelectedItem();
 if(u != null) {
u.changeSalary(Integer.parseInt(howMuchChange.getText()));
 textInfo.setText("Age is" + u.getAge() + ", " + 
 "Salary is" + u.getSalary() + ", " + 
 "Relationshp:" + u.getMarried());
howMuchChange.clear();
 } 
}
});

 buttonAddUser.setOnAction(new EventHandler<ActionEvent>() {
@Override
 public void handle(ActionEvent e) {
 String m = married.getText();
 boolean mm = (m.equals("married"))? true:false;
 User u = new User(name.getText(), Integer.parseInt(age.getText()), 
 Integer.parseInt(salary.getText()), mm);
users.add(u);
userBox.getItems().addAll(u);
name.clear();
age.clear();
salary.clear();
married.clear();
}
});

 Scene scene = new Scene(root, WIDTH, HEIGHT);
primaryStage.setTitle("Company");
primaryStage.setScene(scene);
primaryStage.show();
}

 public static void main(String[] args) {
launch(args);
}

 Group root = new Group();

 VBox strings = new VBox();

 HBox buttonBox = new HBox();
 ComboBox<User> userBox = new ComboBox<>();
 Button buttonGetInfo = new Button("Info");
 Text textInfo = new Text();

 HBox changeSalaryBox = new HBox();
 Button buttonChangeSalary = new Button("Change salary");
 TextField howMuchChange = new TextField();

 HBox addUserBox = new HBox();
 Button buttonAddUser = new Button("Add User");
 TextField name = new TextField();
 TextField age = new TextField();
 TextField salary = new TextField();
 TextField married = new TextField();

 final private int WIDTH = 1000;
 final private int HEIGHT = 600;

 private ArrayList<User> users = new ArrayList<>();

}

Фільтри

Тепер додамо «фільтрацію» співробітників за ознаками. Знову ж таки, списки для фільтрів будемо додавати з використанням ComboBox за тією ж самою логікою.

package company;

/* */

public class Company extends Application {

 public void start(Stage primaryStage) throws Exception {

 /* */

ageFilterBox.getItems().addAll(
 "no matter", 
 "over 20",
 "over 30", 
 "over 40"
);

 salaryFilterBox.getItems().addAll( 
 "no matter",
 "over 150",
 "over 250",
 "over 500"
);

 relationshipFilterBox.getItems().addAll( 
 "no matter",
"married",
"single"
);


 /* */
strings.getChildren().add(filters);
strings.getChildren().add(resultFilter);

 /* */

filters.setSpacing(10);
 filters.getChildren().add(new Text("Age"));
filters.getChildren().add(ageFilterBox);
 filters.getChildren().add(new Text("Salary"));
filters.getChildren().add(salaryFilterBox);
 filters.getChildren().add(new Text("Relationship"));
filters.getChildren().add(relationshipFilterBox);
filters.getChildren().add(filter);

 /* */

 filter.setOnAction(new EventHandler<ActionEvent>() {
@Override
 public void handle(ActionEvent e) {
 int age;
 int index = ageFilterBox.getSelectionModel().getSelectedIndex();
 age = (index == 0)? 0: (index == 1)? 21: (index == 2)? 31: 41;

 int salary;
 index = salaryFilterBox.getSelectionModel().getSelectedIndex();
 salary = (index == 0)? 0 : (index == 1)? 151 : (index == 2)? 251:501;

 boolean relate;
 index = relationshipFilterBox.getSelectionModel().getSelectedIndex();
 relate = (index == 1)? true: (index == 2)? false: true;

 List<User> list;
 if(index != 0) { list = users.stream().
 filter(u -> u.age > age).
 filter(u -> u.salary > salary).
 filter(u -> u.married == relate).
 collect(Collectors.toList()); }

 else { list = users.stream().
 filter(u -> u.age > age).
 filter(u -> u.salary > salary).
 collect(Collectors.toList()); }

 String res = "";
 for(u User: list) {
 res += u.toString() + ", ";
}

resultFilter.setText(res);

}
});

 /* */
}

 /* */

 HBox filters = new HBox();
 ComboBox<String> ageFilterBox = new ComboBox<>();
 ComboBox<String> salaryFilterBox = new ComboBox<>();
 ComboBox<String> relationshipFilterBox = new ComboBox<>();
 Button filter = new Button("filter");
 Text resultFilter = new Text();

 /* */

}

Готово!

Що це було

Сама по собі програма не являє ніякої корисності і була написана виключно для того, щоб познайомитися з JavaFX і її інструментами. У деяких місцях, наприклад, при зміні зарплати, не враховуються варіанти, коли не вибрано користувач, або коли введена рядок: в цих випадках буде з’являтися помилка. Те ж саме стосується полів, куди вводиться інформація при додаванні нових співробітників. І, нарешті, помилка буде виникати, якщо не вибрано якесь значення в будь-якому з випадаючих списків. При бажанні, кожен може додати свій «обхід» цих моментів.

При написанні фільтрів, до речі, я використовував відомі StreamAPI і -вирази, які скорочують код, додають в нього легкість розуміння і свій шарм.

Джерела:

  1. JavaFX 8 — Oracle Help Center
  2. Трохи про створення та історичних модифікаціях JavaFX
  3. Чудова стаття vedenin1980 про StreamAPI і -вираження

Related Articles

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Close