I have a problem with Context menu. Following this topic I found that there is a limitation when I try to load Context menu insight JavaFX Task. I tested to implement Platform.RunLater() but without any success.
static ContextMenu contextMenuPanel;
public static BorderPane stageContextMenu(BorderPane bp)
{
Platform.runLater(new Runnable() {
@Override public void run() {
contextMenuPanel = new ContextMenu();
}
});
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("Close");
item3.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
//flow.getChildren().remove(bp);
}
});
contextMenuPanel.getItems().addAll(item1, item2, item3);
bp.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>()
{
@Override
public void handle(ContextMenuEvent event)
{
//contextMenu.hide();
contextMenuPanel.show(bp, event.getScreenX(), event.getScreenY());
event.consume();
}
});
bp.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent event)
{
contextMenuPanel.hide();
}
});
return bp;
}
Other possible solution is:
One way is to define a custom skin for the context menu which does not use a PopupWindow or does not create a PopupWindow in it's constructor.
Can you help me to implement this?
P.S I tested this code
static private StringBuilder stringBuilder = new StringBuilder();
private static ContextMenu contextMenu;
private static CountDownLatch menuCreated = new CountDownLatch(1);
static ContextMenu contextMenuPanel;
public static BorderPane stageContextMenu(BorderPane bp) throws InterruptedException
{
new Button();
Task task = new Task()
{
@Override
protected Void call() throws Exception
{
Platform.runLater(new Runnable()
{
@Override
public void run()
{
try
{
contextMenu = new ContextMenu();
contextMenu.setId("Test ID");
menuCreated.countDown();
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
}
}
});
return null;
}
};
new Thread(task).start();
menuCreated.await();
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("Close");
item3.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent e)
{
//flow.getChildren().remove(bp);
}
});
contextMenuPanel.getItems().addAll(item1, item2, item3);
bp.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>()
{
@Override
public void handle(ContextMenuEvent event)
{
//contextMenu.hide();
contextMenuPanel.show(bp, event.getScreenX(), event.getScreenY());
event.consume();
}
});
bp.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent event)
{
contextMenuPanel.hide();
}
});
return bp;
}
But the result is unsuccessful - JavaFX Task hangs.
Consider the following code which creates a context menu from task. If you get rid of the latch the context menu wont be constructed at the time when its id is requested.