Je suis novice sur javafx. Je veux afficher le menu contextuel sur clic droit de la souris. Je trouve un tutoriel ici et ici mais je ne comprends pas. Je veux créer un menu contextuel qui s'affiche en image sur ce lien.
En ce moment, je crée une scène mais je ne veux pas de scène. J'ai besoin d'afficher un menu contextuel qui montre un clic droit et se ferme lorsque je clique n'importe où.
Voici mon code dans lequel j'utilise stage mais je dois ouvrir un menu contextuel comme ci-dessus.
public void MouseClickedOnTree(MouseEvent event) {
if (event.isSecondaryButtonDown()) {
System.out.println("secondary press");
final Stage optionstage = new Stage();
VBox vBox = new VBox(5);
vBox.setMinHeight(50);
vBox.setMinWidth(50);
Button btnNewTestBed = new Button("New Testbed");
btnNewTestBed.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
try {
optionstage.close();
stage.show();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
});
Button btnOpenTestbed = new Button("Open Testbed");
btnOpenTestbed.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
optionstage.close();
}
});
optionstage.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ESCAPE) {
System.out.println("click on escape");
//Stage sb = (Stage) label.getScene().getWindow();//use any one object
if(optionstage.isShowing())
optionstage.close();
}
}
});
vBox.getChildren().addAll(btnNewTestBed, btnOpenTestbed);
optionstage.setScene(new Scene(vBox, 100, 100));
//stage.setScene(new Scene(new Group(new Text(50,50, "my second window"))));
optionstage.setX(event.getSceneX());
optionstage.setY(event.getScreenY());
optionstage.initStyle(StageStyle.UNDECORATED);
optionstage.show();
}
Veuillez me fournir tout lien ou référence.
Le contexte de votre code n'est pas très clair: est-ce à l'intérieur d'un gestionnaire d'événements? Si oui, à quoi sert-il un gestionnaire d'événements? Si non, quelle est la variable event
dans la déclaration d'ouverture if
?
Les deux liens que vous fournissez sont assez complexes. sous JavaFX (contrairement à Swing), vous ne devriez envisager de sous-classer que les classes de nœuds existantes pour des cas d'utilisation assez avancés. Vous n'avez pas besoin de ce niveau de complexité pour créer un menu contextuel.
Le moyen le plus simple de créer un menu contextuel est d'utiliser une Control
(ou une sous-classe); il vous suffit de créer une ContextMenu
, d'y ajouter MenuItem
s et de la définir comme contextMenu
sur votre contrôle:
TextField textField = new TextField("Type Something"); // we will add a popup menu to this text field
final ContextMenu contextMenu = new ContextMenu();
MenuItem cut = new MenuItem("Cut");
MenuItem copy = new MenuItem("Copy");
MenuItem paste = new MenuItem("Paste");
contextMenu.getItems().addAll(cut, copy, paste);
cut.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Cut...");
}
});
// ...
textField.setContextMenu(contextMenu);
Si vous voulez utiliser une ContextMenu
sur un nœud qui n'est pas une Control
(une Pane
ou une Shape
, par exemple), vous n'avez pas de méthode setContextMenu(...)
, vous avez donc besoin d'un peu plus de travail:
final AnchorPane pane = new AnchorPane();
// fill pane with nodes, etc
// create context menu and menu items as above
pane.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isSecondaryButtonDown()) {
contextMenu.show(pane, event.getScreenX(), event.getScreenY());
}
}
});
Voir le Javadocs for ContextMenu
ou le tutorial pour plus de détails.
James_D a déjà fourni un exemple de travail cohérent avec les tutoriels, mais j'ai rencontré des problèmes avec celui-ci. James a raison de dire que pour tout nœud de type Control, la manière correcte d’ouvrir le menu contextuel consiste à utiliser Control.setContextMenu () . Cependant, contrairement au didacticiel, la méthode correcte pour enregistrer un menu contextuel sur des nœuds non-Control est la suivante (Java 8):
pane.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
contextMenu.show(pane, event.getScreenX(), event.getScreenY());
event.consume();
});
pane.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
contextMenu.hide();
});
Ceci est cohérent avec ce que setContextMenu fait en coulisse. L'implémentation setContextMenu de Controls utilise et consomme ContextMenuEvent mais not ne consomme pas l'événement de la souris. Cela signifie que si vous enregistrez un écouteur pour MouseEvent dans un volet et que vous utilisez setContextMenu sur un contrôle dans le volet, un clic droit sur le contrôle ouvrira les deux menus contextuels: et consomme le MouseEvent. J'ai découvert dans mon code avec openjdk-8 que l'enregistrement d'un écouteur ContextMenuEvent dans le volet résout ce problème de menu contextuel en double.
J'ai également constaté qu'un menu enregistré sur un volet ne disparaît pas par défaut lorsque l'utilisateur clique ailleurs. L'écouteur MOUSE_PRESSED qui ne consomme pas son événement garantit que le menu est ignoré alors qu'il devrait l'être.
La réponse de James_D en haut est fausse. Si vous cliquez avec le bouton droit de la souris sur ce volet non contrôlé, mais que vous cliquez à l'extérieur, le menu contextuel ne se cache pas.
J'aime la réponse de fuzzyBSc, mais celle-ci est plus succincte. Les deux vont marcher.
pane.setOnContextMenuRequested(e ->
contextMenu.show(pane, e.getScreenX(), e.getScreenY()));