JPopupMenu方向键导航失效与固定位置及setLocationRelativeTo用法咨询
问题解决办法
1. 方向键导航失效问题
失效原因
- 按键判断逻辑错误:方向键属于功能键,不能通过
getKeyChar()获取值,需要用getKeyCode()匹配KeyEvent.VK_UP、KeyEvent.VK_DOWN常量 - 索引计数错误:
JPopupMenu的菜单项索引从0开始,你代码中使用1/2/3作为判断值,永远无法匹配到正确选项 - 监听API选择错误:
KeyListener仅在组件持有焦点时生效,JPopupMenu默认不会主动获取焦点,因此监听逻辑不会触发 - 菜单项不可聚焦:你注释了
JMenuItem的setText()方法,无文本的菜单项默认会被Swing判定为不可聚焦,无法响应导航操作
修复方案
废弃KeyListener,改用Swing高阶的*键绑定(Key Binding)*API,该API不需要组件持有焦点即可触发。如果不需要显示菜单项文本,可以将文字颜色设为透明,不要直接注释setText():
// 给弹出菜单添加上下方向键绑定 InputMap inputMap = popgraphics.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap actionMap = popgraphics.getActionMap(); // 上方向键逻辑 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "selectPrevious"); actionMap.put("selectPrevious", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { int current = popgraphics.getSelectionModel().getSelectedIndex(); int total = popgraphics.getComponentCount(); if (current <= 0) { popgraphics.getSelectionModel().setSelectedIndex(total - 1); } else { popgraphics.getSelectionModel().setSelectedIndex(current - 1); } } }); // 下方向键逻辑 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "selectNext"); actionMap.put("selectNext", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { int current = popgraphics.getSelectionModel().getSelectedIndex(); int total = popgraphics.getComponentCount(); if (current >= total - 1 || current == -1) { popgraphics.getSelectionModel().setSelectedIndex(0); } else { popgraphics.getSelectionModel().setSelectedIndex(current + 1); } } });
2. 弹出菜单位置超出边界问题
问题原因
你调用graghics.getLocation()获取的是按钮相对于父容器的坐标,而JPopupMenu.setLocation()要求传入的是屏幕绝对坐标,坐标体系不匹配会导致位置偏移,且手动设置坐标没有做边界检测,自然会超出窗口/屏幕范围。另外你代码中存在笔误,将graphics拼成了graghics,也会导致坐标获取错误。
setLocationRelativeTo()正确用法
setLocationRelativeTo(Component c)方法会将组件中心对齐到参数组件的中心,参数为null时对齐到屏幕中心。如果需要让菜单固定在Graphics按钮的正下方,不需要手动计算坐标,直接使用JPopupMenu自带的show()方法即可,该方法会自动计算坐标并做边界检测,避免超出屏幕:
// 第一个参数为依附的按钮,后两个为相对于按钮的x、y偏移量 popgraphics.show(graphicsButton, 0, graphicsButton.getHeight());
如果一定要用setLocation()手动设置,需要先将按钮坐标转为屏幕坐标:
Point screenLoc = graphicsButton.getLocationOnScreen(); popgraphics.setLocation(screenLoc.x, screenLoc.y + graphicsButton.getHeight());
内容的提问来源于stack exchange,提问作者Ghulam Tahir
相关产品推荐
相关产品推荐

