2015-08-14 2 views
0

Я реализую редактор документов с клипсами JavaFX8 и e (fx) и хочу, чтобы пользователь был проинформирован, когда экспорт (запись на диск) продолжается. Я использую основной (GUI) поток для этого, поскольку я хочу заблокировать gui во время этой операции (которая занимает 2-3 секунды). Во время этой операции я хочу показать небольшое всплывающее окно, чтобы сообщить пользователю, что экспорт продолжается, ничего необычного.Диалоговое окно JavaFX 8

@FXML 
    public void export() { 
     Dialog dialog = new Dialog(); 
     dialog.setContentText("exporting ..."); 
     dialog.show(); 

     // some lenghty methods come here, ~equivalent to Thread.sleep(3000); 

     dialog.hide(); 
    } 

При нажатии на соответствующую кнопку, которая вызывает метод экспорта, я как-то два диалога, один из них не закрывается и остается открытым после того, как метод закончил.

enter image description here

ли кто-то имеет представление о том, что здесь происходит? Я действительно заинтересован в простом решении, мне не нужно иметь индикатор выполнения и т. Д.

Еще одна возможность - показать курсор ожидания перед началом работы и вернуться к курсору по умолчанию после этого , К сожалению, это тоже не работает. Я понимаю, что пользовательский интерфейс заблокирован во время «длительной» операции, но я не знаю, почему я не могу изменить пользовательский интерфейс до и после этой операции.

ответ

0

Ваш пример не очень полный - однако я бы рекомендуется использовать один из двух подходов. Тем не менее, вы не ставите длинный процесс в фоновый поток, который будет ЗАМОРОЗИТЬ ваше приложение. Вы хотите разгрузить этот процесс.

1) Используйте диалог ControlsFX, у которого есть оповещение о запуске программы. Свяжите свою работу либо с Задачей, либо с Службой, и предоставьте это оповещение. Это выдает предупреждение, пока поток активен, и будет автоматически закрывать его, когда это будет сделано. Если у вас есть значения промежуточного прогресса, его можно использовать для обновления индикатора выполнения.

Или, если вы не хотите использовать этот диалог, вы могли бы сделать что-то вроде этого:

Alert progressAlert = displayProgressDialog(message, stage); 
    Executors.newSingleThreadExecutor().execute(() -> { 
      try { 
       //Do you work here.... 
       Platform.runLater(() ->forcefullyHideDialog(progressAlert)); 
      } catch (Exception e) { 
       //Do what ever handling you need here.... 
       Platform.runLater(() ->forcefullyHideDialog(progressAlert)); 
      } 

    }); 

private Alert displayProgressDialog(String message, Stage stage) { 
     Alert progressAlert = new Alert(AlertType.NONE); 
     final ProgressBar progressBar = new ProgressBar(); 
     progressBar.setMaxWidth(Double.MAX_VALUE); 
     progressBar.setPrefHeight(30); 

     final Label progressLabel = new Label(message); 
     progressAlert.setTitle("Please wait...."); 
     progressAlert.setGraphic(progressBar); 
     progressAlert.setHeaderText("This will take a moment..."); 

     VBox vbox = new VBox(20, progressLabel, progressBar); 
     vbox.setMaxWidth(Double.MAX_VALUE); 
     vbox.setPrefSize(300, 100); 
     progressAlert.getDialogPane().setContent(vbox); 
     progressAlert.initModality(Modality.WINDOW_MODAL); 
     progressAlert.initOwner(stage); 
     progressAlert.show(); 
     return progressAlert; 
    } 
private void forcefullyHideDialog(javafx.scene.control.Dialog<?> dialog) { 
    // for the dialog to be able to hide, we need a cancel button, 
    // so lets put one in now and then immediately call hide, and then 
    // remove the button again (if necessary). 
    DialogPane dialogPane = dialog.getDialogPane(); 
    dialogPane.getButtonTypes().add(ButtonType.CANCEL); 
    dialog.hide(); 
    dialogPane.getButtonTypes().remove(ButtonType.CANCEL); 
} 
+0

Спасибо за ваш ответ. Я понимаю, что использование длинных операций в другом потоке - это рекомендуемый способ сделать это, я просто надеялся, что есть более простой способ, поскольку создание задач/сервисов для этих операций делает код более сложным (также обработка отладки (включая показ предупреждений) более сложный). Кроме того, я должен убедиться, что пользователь не нажимает никаких кнопок во время операции (это не имеет никакого смысла в моем приложении). Вот почему я думал, что использование потока приложений - это путь, так как я хочу, чтобы пользовательский интерфейс был заблокирован. –

+0

Мое решение выше не использует задачу или службу, просто вращая нить. Использование progressAlert.initModality (Modality.WINDOW_MODAL); & progressAlert.initModality (Modality.WINDOW_MODAL); progressAlert.initOwner (stage); вы гарантируете, что этап с процессом не будет доступен, пока поток не будет завершен. Используйте Application Modal для полной блокировки пользовательского интерфейса. Скручивание продолжительного процесса в потоке пользовательского интерфейса приведет к тому, что пользовательский интерфейс будет заморожен, и, скорее всего, пользователь заставит выйти из приложения. При таком подходе анимация подтверждает, что приложение все еще работает. –