You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX右键菜单不显示求助:事件触发但无弹窗

JavaFX ContextMenu 无法显示问题

开发大型项目时遇到ContextMenu无法显示的问题,为排查是否是项目复杂度导致,搭建了简单测试项目,但右键菜单仍无法正常显示——仅能触发onContextMenuRequested事件(控制台输出一串"2222222222222222222222222222"),怀疑存在代码写法问题。

测试代码如下:

package org.example.testinterface;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        ContextMenu contextMenu = new ContextMenu(new MenuItem("Удалить"));
        contextMenu.setStyle("-fx-background-color: red");
        Canvas canvas = new Canvas(1500, 1000);
        canvas.setOnContextMenuRequested(contextMenuEvent -> {
            System.out.println("2222222222222222222222222222");
            contextMenu.show(canvas.getScene().getWindow(), contextMenuEvent.getX(), contextMenuEvent.getY());
        });
        AnchorPane root = new AnchorPane(canvas);
        Scene scene = new Scene(root, 1500, 1000);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

问题原因

调用contextMenu.show()时,传入窗口作为所有者,但contextMenuEvent.getX()/getY()返回的是相对于Canvas节点的局部坐标,而非屏幕坐标。这会导致菜单被渲染到屏幕外,看起来像是未显示。

修复方案

方案1:以Canvas作为菜单所有者(推荐)

将show()方法的所有者改为canvas,此时传入的坐标会自动相对于节点计算,菜单将正确显示在点击位置:

canvas.setOnContextMenuRequested(contextMenuEvent -> {
    System.out.println("2222222222222222222222222222");
    contextMenu.show(canvas, contextMenuEvent.getX(), contextMenuEvent.getY());
});

方案2:转换坐标为屏幕坐标(如果需保留窗口作为所有者)

将节点局部坐标转换为屏幕坐标后传入show()方法:

canvas.setOnContextMenuRequested(contextMenuEvent -> {
    System.out.println("2222222222222222222222222222");
    double screenX = canvas.localToScreen(contextMenuEvent.getX(), contextMenuEvent.getY()).getX();
    double screenY = canvas.localToScreen(contextMenuEvent.getX(), contextMenuEvent.getY()).getY();
    contextMenu.show(canvas.getScene().getWindow(), screenX, screenY);
});

方案3:直接绑定ContextMenu到节点(最简洁)

JavaFX支持直接为节点设置ContextMenu,无需手动监听事件,系统会自动处理显示逻辑:

ContextMenu contextMenu = new ContextMenu(new MenuItem("Удалить"));
contextMenu.setStyle("-fx-background-color: red");
Canvas canvas = new Canvas(1500, 1000);
// 直接绑定菜单到Canvas
canvas.setContextMenu(contextMenu);

内容的提问来源于stack exchange,提问作者ramzes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 20:35:58