Как проверить свойство setVisible для индикатора прогресса

Я пишу программу javafx в программе, мне нужно поместить индикатор выполнения после входа в систему, он должен ждать определенное время, пока он не загрузит необходимые объекты с сервера. Я новичок в javafx, мне нужен способ проверить свойство setVisible (boolean) из контроллера, при инициализации оно должно быть невидимым, и нет проблем установить для него значение false в методе инициализации, но в контроллере после инициализации я думаю, что должен проверить перемены. есть ли метод, который я мог бы использовать для проверки этого изменения свойства?

     //////pseudocode
@FXML ProgressIndicator pi;
public void initialize(...){
 PI.setVisible(false); 
  }
@FXML public void buttonOnClick(){
Thread t1=new Thread(new Runnable(....)) // A thread to load data
 t1.start
pi.setVisible(true); //HERE IS MY PROBLEM
Thread t2;//a thread to increase progress
  t2.start();
t1.join();
}

person Faroun    schedule 27.08.2019    source источник
comment
Я правильно понимаю вашу проблему? Вы хотите установить для индикатора прогресса значение true после инициализации во время загрузки данных?   -  person poisn    schedule 27.08.2019
comment
Да, это правильно   -  person Faroun    schedule 27.08.2019
comment
В классе, где вы загружаете данные с сервера, вы можете вызвать индикатор прогресса с геттером, например: ClassName.getProgressIndicator().setVisible(true);   -  person poisn    schedule 27.08.2019
comment
Это не моя проблема, я могу вернуть индикатор выполнения, но я не могу проверить изменение свойства   -  person Faroun    schedule 27.08.2019
comment
Например, в Java Frame вы можете выполнить JFrame.validate(), чтобы фрейм обновил изменения.   -  person Faroun    schedule 27.08.2019
comment
Может ли это в конечном итоге помочь вам? stackoverflow.com/questions/14423109 /   -  person poisn    schedule 27.08.2019
comment
Предоставьте минимально воспроизводимый пример, демонстрирующий проблему.   -  person kleopatra    schedule 27.08.2019
comment
это не fx-2, или нет? Если да, обновите до более новой версии (текущая версия openjfx12)   -  person kleopatra    schedule 27.08.2019
comment
@kleopatra Я только что добавил псевдокод   -  person Faroun    schedule 27.08.2019
comment
Я предполагаю, что вы просто задаете неправильный вопрос, чтобы получить ответ на проблему, которую пытаетесь решить. Но я думаю, что понимаю, что вы хотите сделать, поэтому я попытаюсь ответить на это, но, возможно, я неправильно понимаю, и мой ответ не актуален.   -  person jewelsea    schedule 28.08.2019


Ответы (1)


Почему понятие validate() обычно недопустимо в JavaFX, а также решение проблем с потоками

Чтобы объяснить некоторые проблемы с вашим первоначальным вопросом и почему этот ответ может не дать прямого ответа на него:

  1. Обычно вам не нужно validate() (т. е. форсировать компоновку подкомпонентов) в JavaFX, так как JavaFX будет делать это автоматически каждый pulse (изучите связанный документ, чтобы лучше понять это).
  2. Иногда вам может понадобиться создать макет pass (что, я думаю, несколько похоже на концепцию явного вызова проверки для JFrame). Но обычно это просто потому, что вы хотите измерить, какими будут размеры чего-либо, как только к нему будет применен css и он будет полностью выложен (это не то, что вы хотите делать здесь).
  3. Вы не должны пытаться что-то изменить в графе сцены вне потока приложения JavaFX, так как это вызовет исключения и условия гонки (т. е. ваш вызов setVisible на индикаторе выполнения в потоке, который вы создали, неверен).
  4. Для некоторые параллельные задачи, такие как отправка логина в службу входа и взаимодействие с пользовательским интерфейсом на основе хода выполнения и результатов задачи.

Что делать вместо этого

Я думаю, вы пытаетесь сделать следующее:

  1. Чтобы создать приглашение для входа в систему, где логика входа происходит в другом потоке
  2. Иметь неопределенное вращение индикатора прогресса, пока вход в систему выполняется в другом потоке.
  3. Индикатор прогресса отображается только во время входа в систему и не отображается после завершения попытки входа (независимо от того, была ли она успешной или неудачной).

не зарегистрирован войти в систему < img src="https://i.stack.imgur.com/XJ1J9.png" alt="выполнен вход">

Пример приложения

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

Следующая строка гарантирует, что индикатор выполнения отображается только во время выполнения службы входа в систему:

progressIndicator.visibleProperty().bind(loginService.runningProperty());

Полный код:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.io.IOException;

public class LoginServiceApp extends Application {
    private LoginService loginService = new LoginService();

    @Override
    public void start(Stage stage) throws IOException {
        Pane loginPane = createLoginPane();
        loginService.setOnSucceeded(event ->
                stage.getScene().setRoot(createAppPane(stage))
        );

        stage.setScene(new Scene(new StackPane(loginPane)));
        stage.show();
    }

    private Pane createLoginPane() {
        GridPane credentialsGrid = new GridPane();
        credentialsGrid.setHgap(10);
        credentialsGrid.setVgap(10);
        TextField usernameField = new TextField("frobozz");
        PasswordField passwordField = new PasswordField();
        credentialsGrid.addRow(0, new Label("Username"), usernameField);
        credentialsGrid.addRow(1, new Label("Password"), passwordField);

        Button loginButton = new Button("Login");
        loginButton.setOnAction(event -> {
            loginService.setUsername(usernameField.getText());
            loginService.setPassword(passwordField.getText());
            loginService.restart();
        });
        loginButton.disableProperty().bind(loginService.runningProperty());

        ProgressIndicator progressIndicator = new ProgressIndicator();
        progressIndicator.visibleProperty().bind(loginService.runningProperty());
        progressIndicator.setPrefSize(20, 20);

        HBox loginControl = new HBox(10, loginButton, progressIndicator);
        VBox loginPane = new VBox(10, credentialsGrid, loginControl);
        loginPane.setPadding(new Insets(10));

        return loginPane;
    }

    private Pane createAppPane(Stage stage) {
        Button logoutButton = new Button("Logout");
        logoutButton.setOnAction(event -> stage.getScene().setRoot(createLoginPane()));
        HBox appPane = new HBox(logoutButton);
        appPane.setPadding(new Insets(10));

        return appPane;
    }

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

    private static class LoginService extends Service<Void> {
        private StringProperty username = new SimpleStringProperty(this, "username");
        public final void setUsername(String value) { username.set(value); }
        public final String getUsername() { return username.get(); }
        public final StringProperty usernameProperty() { return username; }

        private StringProperty password = new SimpleStringProperty(this, "password");
        public final void setPassword(String value) { password.set(value); }
        public final String getPassword() { return password.get(); }
        public final StringProperty passwordProperty() { return password; }

        @Override
        protected Task<Void> createTask() {
            final String _username = getUsername();
            final String _password = getPassword();
            return new Task<Void>() {
                @Override
                protected Void call() throws Exception {
                    // Simulate a long call to a login service,
                    // using the username and password we saved when the task was created.
                    // If login fails, an exception can be raised to report it and the
                    // caller starting the service can monitor setOnException to handle it.
                    // Or the Task could return a result value instead of void and the caller
                    // could monitor the value property of the task in addition to the exception handler.
                    Thread.sleep(1_000);
                    return null;
                }
            };
        }
    }
}
person jewelsea    schedule 27.08.2019
comment
Большое спасибо, это было так полезно .. Я думаю, что застрял в старой Java, ха-ха - person Faroun; 28.08.2019
comment
Я хочу задать вам вопрос, но я не хочу задавать его как новый пост ... как сделать размер шрифта в метке или в текстовых компонентах, рассчитанный в соответствии с родительским контейнером. Есть ли свойство в fxml или должно это сделать динамически? и как? - person Faroun; 28.08.2019
comment
Для вашего дополнительного вопроса о динамическом размере шрифтов см.: автоматическое изменение размера javafx и заполнение кнопок и Привязать размер шрифта в JavaFX? - person jewelsea; 28.08.2019