使用javafx创建等待/通知窗口的最佳用途是什么?

使用javafx创建等待/通知窗口的最佳用途是什么?,java,multithreading,javafx,wait,Java,Multithreading,Javafx,Wait,我只想创建一次弹出窗口,并通过for循环更改内容;(对于删除的每个文件)。我想回答是/否/否/是/否。所以我需要一个wait()来显示带有第一个电影内容的弹出窗口。例如,如果我说“不”,我希望在第二部电影之前,在aim中解锁线程。在这种情况下,弹出内容会随着第二部电影而改变,我会再次等待(),直到我通过按钮等进行应答 我尝试了很多事情都没有成功,但我得到了以下错误: Exception in thread "JavaFX Application Thread" java.lang.Illegal

我只想创建一次弹出窗口,并通过for循环更改内容;(对于删除的每个文件)。我想回答是/否/否/是/否。所以我需要一个wait()来显示带有第一个电影内容的弹出窗口。例如,如果我说“不”,我希望在第二部电影之前,在aim中解锁线程。在这种情况下,弹出内容会随着第二部电影而改变,我会再次等待(),直到我通过按钮等进行应答

我尝试了很多事情都没有成功,但我得到了以下错误:

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)
我在
对话框中遇到问题。notify()
也许我没有在同一个对话框对象上应用notify(),但事实就是这样,不是吗

提前感谢您的帮助

这是我的部分代码:搜索
//查看代码中的此处
,查看主要行

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;");
公共类HomeController{
@FXML
自有品牌家居;
@FXMLViewFlowContext
私有视图流上下文;
更名电影;
SimpleBoleAnProperty noAllProperty=新SimpleBoleAnProperty(false);
SimpleBoleAnProperty yesAllProperty=新SimpleBoleAnProperty(false);
SimpleBoleanProperty continuePopup=新的SimpleBoleanProperty(false);
ArrayList arrayFile=新的ArrayList();
阶段性;
布尔值firstFile=false;
JFXDialogLayout内容;
jfx对话框;
@施工后
public void init()引发FlowException,VetoException{
设置=(设置)context.getRegisteredObject(“设置”);
内容=新的JFXDialogLayout();
dialog=newJFXDialog((StackPane)context.getRegisteredObject(“根”),content,JFXDialog.DialogTransition.CENTER);
setOnDragOver(新的EventHandler()){
@凌驾
公共无效句柄(DrageEvent事件){
Dragboard Dragboard=event.getDragboard();
if(dragboard.hasFiles()){
event.acceptTransferModes(TransferMode.ANY);
}否则{
event.consume();
}
}
});
//降落在水面上
setOnDragDrop(新的EventHandler()){
@凌驾
公共无效句柄(DrageEvent事件){
Dragboard Dragboard=event.getDragboard();
布尔成功=假;
if(dragboard.hasFiles()){
arrayFile=新的ArrayList();
成功=真实;
noAllProperty.set(false);
yesAllProperty.set(false);
dragboard.getFiles().forEach(文件->{
if(Files.isDirectory(file.toPath())){
try(Stream path=Files.walk(path.get(file.toURI())){
path.forEach(文件路径->{
if(Files.isRegularFile(filePath))
添加(文件路径);
});
}捕获(IOE异常){
e、 printStackTrace();
} 
}else if(Files.isRegularFile(file.toPath()))
add(file.toPath());
});
}
事件。setDropCompleted(成功);
event.consume();
arrayFile.forEach(文件->{
film=新重命名文件(新文件(File.toString()),设置);
如果(!noAllProperty.getValue()){
if(film.getNameWithoutExt().length()>0){
如果(!yesAllProperty.getValue()){
试一试{
firstFile=true;
contentPopup();
如果(第一个文件){
dialog.show();
对话框。设置套圈(错误);
firstFile=false;
}
//看这里
等待弹出窗口(对话框);
}捕获(FlowException | InterruptedException e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}           
}否则{
film.applyRename(film.getCleanName());
}
}
}
});
}
});
}
公共同步void waitPopup(JFXDialog对话框){
//对于每个特殊事件,此保护仅循环一次,这可能不会发生
//成为我们等待的事件。
而(!continuePopup.getValue()){
试一试{
dialog.wait();
}捕获(中断异常e){}
}
}
公共同步void notifyPopup(JFXDialog对话框){
continuePopup.setValue(真);
dialog.notifyAll();
}
私有void contentPopup()引发FlowException、InterruptedException{
JFXButton ButtonyESPupPreName=新的JFXButton(“是”);
ButtonySpupPreName.setPrefHeight(30);
ButtonySpupPreName.setPrefWidth(70);
ButtonySpupPreName.setId(“ButtonySpupPreName”);
ButtonySpupPreName.setButtonType(ButtonType.凸起);
ButtonyESPupPreName.setOnAction(e->{film.applyRename(film.getCleanName());continuepop.setValue(true);notifyPopup(dialog);});//查看此处
ButtonySpupPreName.setStyle(“-fx文本填充:白色;-fx背景色:#5264AE;-fx字体大小:14px;”);
JFXButton buttonNoPopupRename=新的JFXButton(“否”);
按钮nopopupRename.setPrefHeight(30);
buttonNoPopupRename.setPrefWidth(70);
setId(“buttonnoppuprename”);
buttonNoPopupRename.setButtonType(ButtonType.Rised);
buttonNoPopupRename.setOnAction(e->{continuePopup.setValue(true);notifyPopup(dialog);});//请看这里
buttonNoPopupRename.setStyle(“-fx文本填充:白色;-fx背景色:#5264AE;-fx字体大小:14px;”);

您必须将等待和通知嵌入同步块中:

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


顺便说一句:只需notify()就足够了。notifyAll(()只有在有多个线程等待时才有意义。

解决问题的方法比您的方法更好:

使需要询问的元素和当前元素的数据可供事件处理程序使用,并在
synchronized( dialog)
{
    dialog.notify();
}
@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();
    }
}