I want to create a popup only once and change the content via the for loop; (for each files dropped). I want to answer yes/no/noAll/yesAll. So I need a wait() just after to show the popup with the first movie content. And if I said "no" for example, I want notify() the thread to be unlock in the aim to reach until the second movie. In this case, The popup content changes with the second movie and I have again a wait() until I answer via the buttons etc.
I tried a lot of things without successfull :/ and I get this error:
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)
I meet a problem on dialog.notify()
Maybe I don't apply the notify() on the same dialog object but it's the case, no ?
Thank you in advance for your help
This is my partial code : Search // LOOK HERE
in the code to see the main lines
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;");
There is a better approach to the problem than your approach:
Make the data about the elements that need to be asked about and the current element available to the event handlers and modify the those values and the UI when an event occurs.
Simplified example that let's you choose Yes
or No
for some items:
@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();
}
}