- •3.1 Лабораторна робота № 1. Створення JavaFx додатку. Авторизація користувачів.
- •Java Persistence api
- •3.1.1. Необхідне програмне забезпечення
- •3.1.2. Налаштування проекту JavaFx-додатку
- •3.1.3. Підключення бази даних
- •3.1.4. Створення моделей та їх маппінг за допомогою jpa
- •3.1.5. Створення допоміжного класу для роботи з моделями
- •3.1.6. Впровадження логіки авторизації користувача
- •Медіа-програвач
- •Табличне представлення данних
- •3.2.1 Вдосконалення коду додатка
- •3.2 Лабораторна робота № 2. Робота з медіа. Реалізація crud за допомогою jpa та TableView.
- •3.2.2 Створення інтерфейсу додатка
- •3.2.3 Створення медіа програвача
- •3.2.4 Впровадження можливості адміністрування користувачів
- •3.3 Лабораторна робота № 3. Використання вбудованого браузеру, будування графіків та створення анімації.
- •Акордеон
- •Анімація у JavaFx
- •Графіки
- •3.3.1 Інтегрування веб-браузеру до проекту
- •3.3.2 Створення графіків
- •3.3.3 Використання елементу акордіон для створення альтернативного варіанту панелі інструментів
- •3.3.4 Створення анімації кнопок
- •3.4 Лабораторна робота № 4. Технологія drag-and-drop у JavaFx-додатках. Використання стилів.
- •Drag-and-Drop
- •Стилювання додатку за допомогою css
- •3.4.1 Drag-and-Drop
- •3.4.2 Додавання можливості стилювання додатку
- •3.4.3 Створення стилів
- •3.5 Лабораторна робота № 5. Робота з JavaFx Scene Builder. 3-d трансформація у JavaFx. Розгортання додатку.
- •JavaFx Scene Builder
- •Трансформація у JavaFx
- •Розгортання JavaFx додатків
- •3.5.1 JavaFx Scene Builder
- •3.5.2 Створення логіки додатка
- •3.5.3 Розгортання додатка
3.2.3 Створення медіа програвача
Через те, що для кожної кнопки потрібно буде індивідуально налаштовувати реакцію на подію натискання, то замість циклу завантаження зображень потрібно викликати метод setButtonsActions(taskbar), в якому буде вся логіка, пов’язана із створенням кнопок.
Створити медіа програвач можна з допомогою одного рядку коду, але це не дасть необхідних навичок, отже потрібно зробити дещо складніше: наприклад розробити до програвача панель, де буде відображатися медіа джерело (шлях до файлу), регулятор гучності, кнопка старт/пауза, кнопка програвання наступного треку та кнопка програвання попереднього треку.
Для цього потрібно створити окремий клас в новому пакеті main з назвою MediaControl.
public class MediaControl extends BorderPane {
private MediaPlayer mp;
private MediaView mediaView;
private boolean stopRequested = false;
private boolean atEndOfMedia = false;
private Label errorLabel;
private Slider volumeSlider;
private HBox mediaBar;
private int fileIndex = -1;
private final StackPane mvPane = new StackPane();
private Label trackLabel = new Label();
private Button playButton = new Button(">");
private Button nextButton = new Button(">>");
private Button prevButton = new Button("<<");
public MediaControl(String mediaDir) {
}
}
MediaPlayer mp — це клас медіа програвача, в конструкторі якого вказується Media, яке буде програватися.
MediaView mediaView — це контейнер для MediaPlayer, в якому буде відображатися зображення.
StackPane mvPane — це контейнер, який буде містити в собі mediaView та mediaBar.
HBox mediaBar — це панель програвача, де будуть розміщатися кнопки, слайдер та напис.
Спочатку необхідно розробити логіку, пов’язану з медіа файлами. Через те що JavaFX має лімітовану кількість розширень медіа файлів, які можуть бути запущені у програвачі, необхідно зробити клас, який буде слугувати фільтром при пошуку файлів в каталозі за допомогою метода listFiles. Отже в пакеті utils створіть наступний клас:
public class FileFilterFx implements FileFilter{
private final String[] okFileExtensions = new String[] {"flv", "fxm", "aif", "aiff", "wav", "mp3"};
@Override
public boolean accept(File file)
{
for (String extension : okFileExtensions)
{
if (file.getName().toLowerCase().endsWith(extension))
{
return true;
}
}
return false;
}
}
Таким чином, okFileExtensions містить всі доступні розширення медіа файлів. В каталозі media потрібно створити каталог з медіа фалами, playlist наприклад.
В конструкторі класу MediaControl потрібно написати наступний код:
File dir = new File(mediaDir);
final File[] files = dir.listFiles(new FileFilterFx());
if (files.length == 0){
errorLabel = new Label("No avalible files was founded");
errorLabel.setStyle("-fx-text-fill: #ff0000;");
this.setCenter(errorLabel);
} else{
this.mp = new MediaPlayer(new Media(getNextFile(files)));
setStyle("-fx-background-color: #bfc2c7;");
changeMP();
mvPane.setStyle("-fx-background-color: black;");
setCenter(mvPane);
mediaBar = new HBox();
mediaBar.setAlignment(Pos.CENTER);
mediaBar.setPadding(new Insets(5, 10, 5, 10));
BorderPane.setAlignment(mediaBar, Pos.CENTER);
}
Якщо жодного файлу, який задовольняє умову не знайдено, то користувачеві буде виведено відповідне повідомлення. В іншому випадку зазантажується перший зі списку файл. changeMP() — це метод, який буде міняти треки, його код наведений нижче:
private void changeMP(){
mvPane.getChildren().remove(mediaView);
mediaView = new MediaView(mp);
mvPane.getChildren().add(mediaView);
mvPane.setAlignment(mediaView, Pos.CENTER);
trackLabel.setText("Track: " + mp.getMedia().getSource() + " ");
stopRequested = false;
setActions();
}
trackLabel — це напис, в якому відображається розміщення треку.
setActions — це метод, який з’вязує MediaPlayer з оброблювачами подій. Виглядає він наступним чином:
private void setActions(){
mp.setOnPlaying(new Runnable() {
public void run() {
if (stopRequested) {
mp.pause();
stopRequested = false;
} else {
playButton.setText("||");
}
}
});
mp.setOnPaused(new Runnable() {
public void run() {
playButton.setText(">");
}
});
mp.setOnEndOfMedia(new Runnable() {
public void run() {
playButton.setText("||");
stopRequested = true;
nextButton.fire();
}
});
}
В основному логіка цього метода відповідає зміненню напису на кнопці старт/пауза. Також тут присутня логіка, яка буде виконуватися після завершення програвання треку — nextButton.fire() імітує натискання користувачем на кнопку «наступний трек».
Тепер потрібно розробити методи, які реалізують логіку отримання наступного та попереднього треку:
public final String getNextFile(File[] files){
if (this.fileIndex >= files.length-1)
this.fileIndex = -1;
return files[++this.fileIndex].toURI().toString();
}
public final String getPrevFile(File[] files){
if (this.fileIndex <= 0)
this.fileIndex = files.length;
return files[--this.fileIndex].toURI().toString();
}
Також необхідно додати можливість зупиняти програвання медіа файлу ззовні:
public void stop(){
if (this.mp != null)
this.mp.stop();
}
Залишилось додати до панелі кнопки з логікою їх роботи, слайдер гучності та напис треку.
Нижче наведена логіка роботи кнопки старт/пауза, її потрібно додати в кінець конструктору класу MediaControl:
playButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
Status status = mp.getStatus();
if (status == Status.UNKNOWN || status == Status.HALTED) {
// don't do anything in these states
return;
}
if (status == Status.PAUSED || status == Status.READY || status == Status.STOPPED) {
mp.play();
} else {
mp.pause();
}
}
});
mediaBar.getChildren().add(playButton);
Кнопка переходу на попередній трек:
prevButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.stop();
mp = new MediaPlayer(new Media(getPrevFile(files)));
mp.play();
changeMP();
}
});
mediaBar.getChildren().add(prevButton);
Кнопка переходу на наступний трек:
nextButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.stop();
mp = new MediaPlayer(new Media(getNextFile(files)));
mp.play();
changeMP();
}
});
mediaBar.getChildren().add(nextButton);
Додавання до панелі пустого інтервалу, напису розміщення файлу, слайдеру гучності:
// Add spacer
Label spacer = new Label(" ");
mediaBar.getChildren().add(spacer);
// Add audio file path label
mediaBar.getChildren().add(trackLabel);
// Add the volume label
Label volumeLabel = new Label("Vol: ");
mediaBar.getChildren().add(volumeLabel);
// Add Volume slider
volumeSlider = new Slider();
volumeSlider.setPrefWidth(70);
volumeSlider.setMaxWidth(Region.USE_PREF_SIZE);
volumeSlider.setMinWidth(30);
volumeSlider.valueProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov) {
if (volumeSlider.isValueChanging()) {
mp.setVolume(volumeSlider.getValue() / 100.0);
}
}
});
volumeSlider.setValue(100);
mediaBar.getChildren().add(volumeSlider);
setBottom(mediaBar);
}
Залишилось підправити декілька моментів в файлі JavafxApp.java:
Написати private MediaControl mediaControl; замість private MediaPlayer mediaPlayer;
Відредагувати метод changeView
private void changeView(Node node) {
view.getChildren().clear();
if (mediaControl!=null)
mediaControl.stop();
view.getChildren().add(node);
}
Створити метод setButtonsActions:
private void setButtonsActions(HBox taskbar){ taskbar.getChildren().add(ButtonCreator.createButton(getClass().getResource("media/images/icon-0.png").toString(), new Runnable() {
public void run() {
mediaControl = new MediaControl(getClass().getResource("media/playlist/").getFile());
changeView(mediaControl);
}
}));
}
Тепер можна запустити додаток і подивитись на результат (рис. 3.9, 3.10).
Рис. 3.9. Вигляд програвача при відсутності файлів
