Введение в JavaFX – Модель шахмат - Сохранение настроек приложения

ОГЛАВЛЕНИЕ

Сохранение настроек приложения

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

Сохранение настроек приложения в Java

// код Java
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

public class Main {
    public static void main(String[] args) {
        // получаем домашний каталог пользователя
        String homeDir = System.getProperty("user.home");

        // они объявлены как final, так что к ним можно получить доступ

        // во внутреннем анонимном классе ниже
        final String settingsFilename =
        homeDir + File.separator + "mySettings.properties";
        final Properties props = new Properties():

        // Загрузка сохраненных настроек
        try {
            FileInputStream input = new FileInputStream(settingsFilename);
            props.load(input);
            input.close();
        } catch(Exception ignore) {
            // исключение игнорируется, поскольку ожидалось, что
       // файл установочных параметров иногда может не существовать
            // при первом запуске приложения он точно не будет существовать
        }

        int savedX;
        try {
            savedX = Integer.parseInt(props.getProperty("xPos", "100"));
        } catch(NumberFormatException e) {
            savedX = 100;
        }

        // похожий код для загрузки savedY, savedWidth, savedHeight пропущен для краткости

        // Создаем и отображаем окно, такой же код, как и выше, исключая то, что при закрытии ничего не делается
        // Также делаем JFrame конечным, чтобы к нему можно было получить доступ
        // во внутреннем анонимном классе
        final JFrame frame = new JFrame("Chess");
        frame.setBounds(savedX, savedY, savedWidth, savedHeight);
        // отличается от предыдущего примера
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        String workingDir = System.getProperty("user.dir");
        String iconFilename = workingDir + File.separator +
            "res" + File.separator + "Icon32.png";
        ImageIcon icon = new ImageIcon(iconFilename);
        frame.setIconImage(icon.getImage());
        frame.setVisible(true);

        frame.addWindowListener(new WindowAdapter() {
            @Override public void windowClosing(WindowEvent e) {
                // Сохраняем настройки при выходе
                Rectangle frameBounds = frame.getBounds();
                props.setProperty("xPos", frameBounds.x);
                props.setProperty("yPos", frameBounds.y);
                props.setProperty("width", frameBounds.width);
                props.setProperty("height", frameBounds.height);

                try {
                    FileOutputStream output = new FileOutputStream(settingsFile);
                    props.store(output, "Saved settings");
                    output.close();
                } catch(Exception ignore) {
                    // если не получается сохранить настройки,
               // в следующий раз будут использоваться настройки по умолчанию
                }

                // выход из приложения
                System.exit(0);
            }
        });
    }
}

Свойства

Класс Properties Java используется для сохранения настроек приложения. Этот класс содержит словарь, состоящий из пар ключ/значение. Метод load используется для загрузки сохраненных свойств, и метод storegetProperty вызывается, чтобы получить значение для определенного ключа. Также передается значение параметра по умолчанию, это значение возвращается, если не установлен ключ в объекте Properties. Мы сохраняем properties, используя метод setProperty. Это один из нескольких способов сохранения настроек приложения в Java. используется для сохранения свойств. Метод

WindowListener (слушатель окна)

Нужно загрузить настройки приложения перед отображением окна, потому что требуется установить сохраненную позицию и местоположение окна. Можно сохранить настройки приложения, добавив WindowListener в JFrame. WindowListener будет отправлено сообщение, когда пользователь попытается закрыть окно приложения. Когда это происходит, размер и местоположение JFrame сохраняются в объекте Properties и затем сохраняются в домашнем каталоге пользователя. Можно выйти из приложения, вызвав System.exit(0).

Сохранение настроек в JavaFX

Можно использовать похожие классы для сохранения настроек приложения в нашем JavaFX классе. Единственное отличие состоит в том, что не требуется добавлять WindowListener, просто нужно обновить функцию onClose класса Stage, чтобы сохранить настройки приложения перед выходом из приложения. Это показано в следующем фрагменте кода:

Сохранение настроек приложения в JavaFX

import java.io.*;
import java.lang.*;
import java.util.*;
import javafx.scene.image.*;
import javafx.stage.*;

// ищем файл настроек в домашнем каталоге пользователя
def homeDir = System.getProperty("user.home");
def settingsFile = "{homeDir}{File.separator}"mySettings.properties";

// загружаем настройки в класс Properties
def props: Properties = new Properties();
try {
    def input: FileInputStream = new FileInputStream(settingsFile);
    props.load(input);
    input.close();
} catch(ignore: Exception) {
// если файл не существует, будут использоваться значения по умолчанию
}

// чтение сохраненных настроек
var savedX: Number;
try {
    savedX = Double.parseDouble(props.getProperty("xPos", "100"));
} catch(e: NumberFormatException) {
    savedX = 100;
}
// похожим образом загружаем настройки savedY, savedWidth и savedHeight

// создаем окно, как и раньше, только добавив вызов saveSettings() в функцию onClose

def stage: Stage = Stage {
    title: "Chess"
    x: savedX, y: savedY, width: savedWidth, height: savedHeight
    icons: [ Image {url: "{__DIR__}res{File.separator}Icon32.png" } ]
    onClose: function() {
        saveSettings();  // save settings before exiting
        System.exit(0);
    }
}

function saveSettings(): Void {
    props.setProperty("xPos", "{stage.x}");
    props.setProperty("yPos", "{stage.y}");
    props.setProperty("width", "{stage.width}");
    props.setProperty("height", "{stage.height}");

    try {
        def output: FileOutputStream = new FileOutputStream(settingsFile);
        props.store(output, "Saved Chess Settings");
        output.close();
    } catch(ignore: Exception) {
        // если настройки не получается сохранить, в следующий раз будут использоваться настройки по умолчанию
    }
}

Как видите, можно использовать такие же классы Java для сохранения настроек приложения в JavaFX, как и используемые в Java приложениях. Это одна из лучших возможностей JavaFX, можно использовать большую библиотеку существующих классов Java в программах на JavaFX. Опыт работы с Java Framework можно применить для программирования на JavaFX.

Нужно заметить, что атрибуты x, y, width и height класса Stage все определены как Numbers. Поэтому, если мы сохраняем их на диске, они все сохраняются с десятичной точкой. Это кажется странным, так как размер и местоположение объекта Stage задается в виде числа пикселей. Не имеет смысла использовать десятичную дробь, так как задаются только целые пиксели, 1.5 пикселя не имеет смысла, может быть только 1 или 2 пикселя. Неизвестно, ошибка это или нет. Мы уже отправляли два сообщения об ошибках в JavaFX, а потому  не уверены,  есть ли смысл в данном случае отправлять другое сообщение об ошибке. Однако кажется странным решение использовать Number вместо Integer (целое число).