2016-10-11 2 views
-2

Я хочу создать всплывающее окно только один раз и изменить содержимое с помощью цикла for; (для каждого сброшенного файла). Я хочу ответить yes/no/noAll/yesAll. Поэтому мне нужно подождать(), чтобы показать всплывающее окно с первым содержимым фильма. И если я сказал «нет», например, я хочу уведомлять() о потоке, который нужно разблокировать, чтобы достичь до второго фильма. В этом случае содержание всплывающее меняется со вторым фильмом, и я опять ждать(), пока не отвечу через кнопку и т.д.Каково хорошее использование для создания окна ожидания/уведомления с помощью javafx?

Я пробовал много вещей без преуспевающего:/и я получаю эту ошибку:

Exception in thread "JavaFX Application Thread" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at controllers.HomeController.notifyPopup(HomeController.java:150) 
    at controllers.HomeController.lambda$1(HomeController.java:208) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) 

я встречаю проблемы на dialog.notify() Может быть, я не наносите уведомит() на том же диалоге объекта, но это так, то нет?

Заранее спасибо за помощь

Это мой частичный код: Поиск // LOOK HERE в коде, чтобы увидеть основные линии

public class HomeController { 


    @FXML 
    private Label home; 

    @FXMLViewFlowContext 
    private ViewFlowContext context; 

    RenameFiles film; 
    SimpleBooleanProperty noAllProperty = new SimpleBooleanProperty(false); 
    SimpleBooleanProperty yesAllProperty = new SimpleBooleanProperty(false); 
    SimpleBooleanProperty continuePopup = new SimpleBooleanProperty(false); 
    ArrayList<Path> arrayFile = new ArrayList<Path>(); 
    Stage stage; 
    Boolean firstFile = false; 
    JFXDialogLayout content; 
    JFXDialog dialog; 

    @PostConstruct 
    public void init() throws FlowException, VetoException { 
    Settings settings = (Settings) context.getRegisteredObject("Settings"); 
    content = new JFXDialogLayout(); 
    dialog = new JFXDialog((StackPane) context.getRegisteredObject("ROOT"), content, JFXDialog.DialogTransition.CENTER); 

    home.setOnDragOver(new EventHandler<DragEvent>() { 
     @Override 
     public void handle(DragEvent event) { 
     Dragboard dragboard = event.getDragboard(); 
     if (dragboard.hasFiles()) { 
      event.acceptTransferModes(TransferMode.ANY); 
     } else { 
      event.consume(); 
     } 
     } 
    }); 

    // Dropping over surface 
    home.setOnDragDropped(new EventHandler<DragEvent>() { 
     @Override 
     public void handle(DragEvent event) { 
     Dragboard dragboard = event.getDragboard(); 
     boolean success = false; 
     if (dragboard.hasFiles()) { 
      arrayFile = new ArrayList<Path>(); 
      success = true; 
      noAllProperty.set(false); 
      yesAllProperty.set(false); 
      dragboard.getFiles().forEach(file -> { 
      if(Files.isDirectory(file.toPath())){ 
       try(Stream<Path> paths = Files.walk(Paths.get(file.toURI()))) { 
       paths.forEach(filePath -> { 
        if (Files.isRegularFile(filePath)) 
        arrayFile.add(filePath); 
       }); 
       } catch (IOException e) { 
       e.printStackTrace(); 
       } 
      }else if (Files.isRegularFile(file.toPath())) 
      arrayFile.add(file.toPath()); 

      }); 
     } 
     event.setDropCompleted(success); 
     event.consume(); 

     arrayFile.forEach(file -> { 
      film = new RenameFiles(new File(file.toString()), settings); 
      if(!noAllProperty.getValue()){ 
      if(film.getNameWithoutExt().length() > 0){ 
       if(!yesAllProperty.getValue()){ 
        try { 
         firstFile = true; 
         contentPopup(); 

         if(firstFile) { 
          dialog.show(); 
          dialog.setOverlayClose(false); 
          firstFile = false; 
         } 
       // LOOK HERE 
         waitPopup(dialog); 

        } catch (FlowException | InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        }   
       }else{ 
       film.applyRename(film.getCleanName()); 
       } 
      } 
      } 
     }); 
     } 
    }); 
    } 
    public synchronized void waitPopup(JFXDialog dialog) { 
     // This guard only loops once for each special event, which may not 
     // be the event we're waiting for. 
     while(!continuePopup.getValue()) { 
      try { 
       dialog.wait(); 
      } catch (InterruptedException e) {} 
     } 
    } 

    public synchronized void notifyPopup(JFXDialog dialog) { 
     continuePopup.setValue(true); 
     dialog.notifyAll(); 
    } 

    private void contentPopup() throws FlowException, InterruptedException{ 

    JFXButton buttonYesPopupRename = new JFXButton("Yes"); 
    buttonYesPopupRename.setPrefHeight(30); 
    buttonYesPopupRename.setPrefWidth(70); 
    buttonYesPopupRename.setId("buttonYesPopupRename"); 
    buttonYesPopupRename.setButtonType(ButtonType.RAISED); 
    buttonYesPopupRename.setOnAction(e -> { film.applyRename(film.getCleanName());continuePopup.setValue(true);notifyPopup(dialog); }); // LOOK HERE 
    buttonYesPopupRename.setStyle("-fx-text-fill:WHITE;-fx-background-color:#5264AE;-fx-font-size:14px;"); 

    JFXButton buttonNoPopupRename = new JFXButton("No"); 
    buttonNoPopupRename.setPrefHeight(30); 
    buttonNoPopupRename.setPrefWidth(70); 
    buttonNoPopupRename.setId("buttonNoPopupRename"); 
    buttonNoPopupRename.setButtonType(ButtonType.RAISED); 
    buttonNoPopupRename.setOnAction(e -> { continuePopup.setValue(true); notifyPopup(dialog); }); // LOOK HERE 
    buttonNoPopupRename.setStyle("-fx-text-fill:WHITE;-fx-background-color:#5264AE;-fx-font-size:14px;"); 
+0

Вам необходимо владеть монитором объекта 'wait()/notify()'. Вы не делаете этого ни в одном из мест. Вы даже не должны пытаться использовать 'wait()/notify()' для чего-то вроде этого. Как вы придумали эту идею? – Kayaman

+0

Случалось ли вам найти в Интернете «java.lang.IllegalMonitorStateException»? – VGR

+0

@ Kayaman, если я этого не делаю, какое решение можно использовать для ожидания ответа пользователя на всплывающее окно? Может быть, я пропустил что-то очень простое. Я никогда не пользовался ожиданием и уведомлением, поэтому я попытался применить его сегодня. Мне тоже это не нравится, но на данный момент я не вижу другого способа сделать то, что хочу: /. –

ответ

2

Существует лучший подход к проблеме, чем ваш подход:.

сделать данные об элементах, которые должны быть задан вопрос о и текущий элемент доступен для обработчиков событий и изменять эти значения и пользовательский интерфейс , когда событие происходит

Упрощенный пример, который позволяет вам выбрать Yes или No для некоторых элементов:.

@Override 
public void start(Stage primaryStage) { 
    Button btn = new Button("Dialog"); 
    List<String> list = Arrays.asList("A", "B", "C", "D"); 
    btn.setOnAction((ActionEvent event) -> { 
     displayDialog(list.iterator()); 
    }); 

    StackPane root = new StackPane(); 
    root.getChildren().add(btn); 

    Scene scene = new Scene(root); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

public static void displayDialog(Iterator<String> iterator) { 
    if (iterator.hasNext()) { 
     Button yes = new Button("Yes"); 
     Button no = new Button("No"); 
     Label text = new Label(iterator.next()); 
     Stage stage = new Stage(); 
     stage.setScene(new Scene(new VBox(text, yes, no))); 
     EventHandler<ActionEvent> handler = evt -> { 
      Labeled source = (Labeled) evt.getSource(); 
      System.out.println("You chose \"" + source.getText() + "\" for \"" + text.getText() + "\""); 

      // procede to next state 
      if (iterator.hasNext()) { 
       // display next item 
       text.setText(iterator.next()); 
      } else { 
       // close "dialog" when no more elements available 
       stage.close(); 
      } 
     }; 
     yes.setOnAction(handler); 
     no.setOnAction(handler); 
     stage.show(); 
    } 
} 
+0

Я поддержал ваш ответ, это именно то, чего я хочу. Он работает отлично. Большое спасибо за этот путь, который мне кажется очень хорошим! –

1

Вы должны встраивать ждать и уведомить в синхронизирована блоке :

synchronized(dialog) 
{ 
    dialog.wait(); 
} 

и

synchronized(dialog) 
{ 
    dialog.notify(); 
} 

BTW: Этого достаточно, чтобы просто уведомить(). NotifyAll (() имеет смысл только, если есть больше чем один ожидающий поток

+0

Я уже пробовал ваше решение, но в этом случае мое приложение замерзает. Я удивлен, потому что я думал, что синхронизированный блок был во втором потоке, но если все приложение заморожено, это скажет, что оно находится в основном потоке? Я применяю ваш блок синхронизации в методе waitPopup и уведомляю всплывающее окно. Должен ли я продолжать использовать цикл while для ожидания?. Именно эту часть я не понимаю. Заранее спасибо –

+0

Поскольку я почти не знаю FX, я не знаю, в каком контексте потока встречаются обратные вызовы GUI.В хорошем старом качели это была отдельная нить (а не основной поток), но все действия GUI происходили в одной и той же теме. Если FX ведет себя аналогично, не рекомендуется блокировать этот поток функцией wait. Как отметил в своем комментарии Кайаман, вы должны искать другой путь. Насколько я знаю, FX управляется событиями (см. Ваши обратные вызовы), поэтому просто выполняйте необходимые действия и возвращайтесь. FX Framework ждет вас для следующего события. – Heri

+0

Хорошо, спасибо. Я отредактировал вопрос с JAVAFX, чтобы быть более ясным. Я проверю ваше предложение. –