私はjavafxの初心者です。右クリックでポップアップメニューを表示したい。チュートリアル ここ と ここ が1つありますが、理解できません。このリンクの画像に表示されるポップアップメニューを作成したい。
現在、ステージを作成していますが、ステージは必要ありません。右クリックで表示されるポップアップメニューを表示して、どこかをクリックすると閉じる必要があります。
これが私がステージを使用しているコードですが、上記のリンクのようなポップアップメニューを操作する必要があります。
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();
}
リンクまたは参照を提供してください。
コードのコンテキストはあまり明確ではありません。これはイベントハンドラ内にありますか?もしそうなら、それは何のためのイベントハンドラですか?そうでない場合、最初のevent
ステートメントのif
は何ですか?
提供する2つのリンクはかなり複雑です。 JavaFXでは(Swingとは異なり)、かなり高度なユースケースでは、既存のNodeクラスのサブクラス化のみを検討する必要があります。ポップアップメニューを作成するためだけに、このレベルの複雑さは必要ありません。
ポップアップメニューを作成する最も簡単な方法は、Control
(またはサブクラス)を使用することです。 ContextMenu
を作成し、MenuItem
sを追加して、コントロールでcontextMenu
として設定するだけです。
_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);
_
NodeでContextMenu
を使用する場合、Control
(a Pane
またはShape
ではありませんたとえば)、setContextMenu(...)
メソッドがないため、もう少し作業が必要です。
_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());
}
}
});
_
James_Dはすでにチュートリアルと一致する実用的な例を提供していますが、私はそれで問題に遭遇しました。 Jamesは、タイプControlのすべてのNodeに対して、コンテキストメニューを開く正しい方法は Control.setContextMenu() を使用することであると述べていますが、チュートリアルに反しています非コントロールノードにコンテキストメニューを登録する正しい方法は、次のとおりです(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();
});
これは、setContextMenuが舞台裏で行うことと一致しています。 ControlsのsetContextMenu実装は ContextMenuEvent を使用および消費しますが、notはマウスイベントを消費します。これは、ペインでMouseEventのリスナーを登録し、ペイン内のコントロールでsetContextMenuを使用する場合、コントロールを右クリックすると、実際に両方のコンテキストメニューが開きます。 MouseEventを消費します。 openjdk-8を使用したコードで、ペインにContextMenuEventリスナーを登録すると、この重複するコンテキストメニューの問題が解決されることがわかりました。
また、ペインに登録されたメニューは、ユーザーが他の場所をクリックしたときに、デフォルトでは閉じないこともわかりました。イベントを消費しないMOUSE_PRESSEDリスナーは、必要なときにメニューを閉じるようにします。
James_Dのより高い答えは間違っています。その非コントロールペインを右クリックしても離れた場所にある場合、コンテキストメニューは自動的に非表示になりません。
私はfuzzyBScの答えが好きですが、これはより簡潔です。どちらも機能します。
pane.setOnContextMenuRequested(e ->
contextMenu.show(pane, e.getScreenX(), e.getScreenY()));