java - JPopupMenu 仅在我按键盘上的菜单键时才跳转几行
问题描述
这很奇怪。当我使用鼠标右键单击时,JPopMenu 按预期工作。但是当我尝试使用键盘上的菜单键显示它时,突出显示会在之前或之后跳几行。
我使用了 PopupMenuListener 以便在使用右键单击时可以直接突出显示一行:
popupMenu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Point point = SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table);
int currentRow = table.rowAtPoint(point);
int currentColumn = table.columnAtPoint(point);
table.changeSelection(currentRow, currentColumn, false, false);
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
这是完整的程序:
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class Test {
private JFrame frame;
private JTable table;
private JScrollPane scrollpane;
public Test() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] head = {"ID","NAME","DOB"};
String[][] data = {
{"1", "Peter", "2001/03/24"},
{"2", "Carlos", "1996/09/02"},
{"3", "Ahmed", "1999/07/07"},
{"4", "John", "1993/10/15"},
{"5", "Kumar", "1991/11/08"}
};
table = new JTable(data, head);
scrollpane = new JScrollPane(table);
table.setDefaultEditor(Object.class, null);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem edit = new JMenuItem("Edit");
JMenuItem delete = new JMenuItem("Delete");
popupMenu.add(edit);
popupMenu.add(delete);
table.setComponentPopupMenu(popupMenu);
popupMenu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Point point = SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table);
int currentRow = table.rowAtPoint(point);
int currentColumn = table.columnAtPoint(point);
table.changeSelection(currentRow, currentColumn, false, false);
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
frame.getContentPane().add(scrollpane);
}
public void setVisible(boolean state) {
frame.setVisible(state);
}
}
解决方案
选择在所选行之后或之前跳转了几条记录
我更进一步,在表格中添加了 20 行,然后缩小了框架以显示滚动条。
弹出窗口始终显示在视口的中间。
这作为默认行为是有意义的,因为弹出窗口可以显示在任何组件上。弹出窗口不知道视口中有一个带有选择逻辑的组件。
以下代码尝试根据是否使用鼠标或键盘显示弹出窗口来自定义弹出/选择行为:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class Test {
private JFrame frame;
private JTable table;
private JScrollPane scrollpane;
public Test() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] head = {"ID","NAME","DOB"};
String[][] data = {
{"1", "Peter", "2001/03/24"},
{"2", "Carlos", "1996/09/02"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"3", "Ahmed", "1999/07/07"},
{"4", "John", "1993/10/15"},
{"5", "Kumar", "1991/11/08"}
};
table = new JTable(data, head);
scrollpane = new JScrollPane(table);
table.setDefaultEditor(Object.class, null);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem edit = new JMenuItem("Edit");
JMenuItem delete = new JMenuItem("Delete");
popupMenu.add(edit);
popupMenu.add(delete);
table.setComponentPopupMenu(popupMenu);
popupMenu.addPopupMenuListener(new PopupMenuListener()
{
private boolean isMouse;
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
isMouse = EventQueue.getCurrentEvent().getID() == MouseEvent.MOUSE_RELEASED;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run()
{
if (isMouse) // change row/cell selection
{
Point point = SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table);
int currentRow = table.rowAtPoint(point);
int currentColumn = table.columnAtPoint(point);
table.changeSelection(currentRow, currentColumn, false, false);
}
else // use current selection
{
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
if (selectedRow == -1) // no row selected
{
popupMenu.setVisible( false );
}
else // reset popup location to selected row
{
Rectangle bounds = table.getCellRect(selectedRow, selectedColumn, false);
popupMenu.show(table, bounds.x, bounds.y + bounds.height);
}
}
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
frame.getContentPane().add(scrollpane);
}
public void setVisible(boolean state) {
frame.setVisible(state);
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> new Test().setVisible(true) );
}
}
使用鼠标时,选择将被更改,并且弹出窗口会显示在鼠标位置。
使用键盘时,弹出位置基于当前选定的单元格。
推荐阅读
- python - 熊猫中的 GroupBy 不使用聚合函数
- javascript - 如何找到用于与 USB 设备交互的功能
- r - 通过 Plotly 在 Shiny 应用程序中绘制的缺失数据
- plot - 如何在 Mathematica 中连续排列多个图?
- ansible - Update a boolean variable in Ansible upon a condition
- sql - VBA/Access INSERT into 将数字字符串作为数字传递的语句
- javascript - 将 PHP 数组转换为 JSON 对象以进行自动完成
- node.js - NodeJS - 无法附加客户端证书以使用 Mocha/Chai-Http 进行测试
- c++ - 适用于头文件的函数别名
- javascript - div style =“value%”的错误,因为它没有执行