Details
-
Bug
-
Resolution: Fixed
-
P3
-
8
Description
We asynchronously populate a ContextMenu using the Service class.
While the service is running we display a dummy MenuItem with a progress indicator.
When the service is finished we populate the Context Menu with the service result.
This worked fine in 2.2.
With 8.0 b84, I am unable to remove the MenuItem with the progress indicator and I am also unable to add new items to the context menu.
See this example:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class TestApp5 extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(final Stage stage) throws Exception {
VBox root = new VBox();
Label label = new Label("ContextMenu");
label.setContextMenu(new MyContextMenu());
root.getChildren().add(label);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private class MyContextMenu extends ContextMenu {
private MyService service;
public MyContextMenu() {
final MenuItem progressItem = new MenuItem();
progressItem.setGraphic(new ProgressIndicator());
service = new MyService();
service.stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State state, Worker.State state1) {
switch (state1) {
case SCHEDULED:
System.out.println("adding progress item");
getItems().add(progressItem);
break;
case SUCCEEDED:
System.out.println("removing progress item");
getItems().remove(progressItem);
System.out.println("adding new item");
getItems().add(new MenuItem("new")); // based on service result.
break;
}
}
});
MenuItem menuItem1 = new MenuItem("First Menu Item");
MenuItem menuItem2 = new MenuItem("Last Menu Item");
setOnShowing(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent windowEvent) {
service.restart();
}
});
getItems().addAll(menuItem1, menuItem2);
}
}
private class MyService extends Service<Void> {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
Thread.sleep(1000);
return null;
}
};
}
}
}
While the service is running we display a dummy MenuItem with a progress indicator.
When the service is finished we populate the Context Menu with the service result.
This worked fine in 2.2.
With 8.0 b84, I am unable to remove the MenuItem with the progress indicator and I am also unable to add new items to the context menu.
See this example:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class TestApp5 extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(final Stage stage) throws Exception {
VBox root = new VBox();
Label label = new Label("ContextMenu");
label.setContextMenu(new MyContextMenu());
root.getChildren().add(label);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private class MyContextMenu extends ContextMenu {
private MyService service;
public MyContextMenu() {
final MenuItem progressItem = new MenuItem();
progressItem.setGraphic(new ProgressIndicator());
service = new MyService();
service.stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State state, Worker.State state1) {
switch (state1) {
case SCHEDULED:
System.out.println("adding progress item");
getItems().add(progressItem);
break;
case SUCCEEDED:
System.out.println("removing progress item");
getItems().remove(progressItem);
System.out.println("adding new item");
getItems().add(new MenuItem("new")); // based on service result.
break;
}
}
});
MenuItem menuItem1 = new MenuItem("First Menu Item");
MenuItem menuItem2 = new MenuItem("Last Menu Item");
setOnShowing(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent windowEvent) {
service.restart();
}
});
getItems().addAll(menuItem1, menuItem2);
}
}
private class MyService extends Service<Void> {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
Thread.sleep(1000);
return null;
}
};
}
}
}