JTable上的JPopupMenu -> 获取创建菜单的单元格

4

我有一个情况,当右键单击JTable时会创建弹出式菜单。 创建弹出式菜单的标准方法如下:

aJTable.setComponentPopupMenu(rightClickMenu);

现在,在注册的操作之后,我无法找出是哪个单元格被右击以弹出菜单。
rightClickMenuItem.addActionListener(new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // Work out what cell was right clicked to generate the menu
    }

});

有关如何实现这一功能的任何想法吗?

在监听器中,为了右键保存单元格点击的值 - Nikolay Kuznetsov
@NikolayKuznetsov那里没有Mouselistener,因为它是使用setComponentPopupMenu方法添加的 - 我被告知这是正确的右键菜单操作方式。 - Ramo
2
@NikolayKuznetsov 当 rightClickMenuItemactionPerformed 方法被触发时,菜单已经显示出来了。弹出菜单实际上是由表格本身触发的。 - MadProgrammer
1
你可以检查弹出窗口本身,但这样会很混乱且不可靠。我认为解决这个问题的首选方案是扩展自定义表并覆盖 JComponent#getPopupLocation 方法。 - MadProgrammer
@MadProgrammer,我现在明白了,谢谢。我也相信这与 getPopupLocation() 有关,即从该方法获取单元格的索引。 - Nikolay Kuznetsov
不要在问候语上浪费四行屏幕空间。翻译后的文本:不要在问候语上浪费四行屏幕空间。 - Andrew Thompson
3个回答

5
惊人的事实是:如果安装了componentPopupMenu,那么一个mouseListener永远不会看到作为popupTrigger的mouseEvent(原因是显示componentPopup由BasicLookAndFeel安装的AWTEventListener全局处理,而该侦听器消耗事件)。
唯一可以看到该触发器的鼠标位置的位置是getPopupLocation(MouseEvent),因此获取它的唯一可靠方法(用于执行位置相关的配置/操作)是@Mad的建议来重写该方法并将值存储在某个地方供稍后使用。
下面的代码片段使用clientProperty作为存储位置:
final JTable table = new JTable(new AncientSwingTeam()) {

    @Override
    public Point getPopupLocation(MouseEvent event) {
        setPopupTriggerLocation(event);
        return super.getPopupLocation(event);
    }

    protected void setPopupTriggerLocation(MouseEvent event) {
        putClientProperty("popupTriggerLocation", 
                event != null ? event.getPoint() : null);
    }
};
JPopupMenu popup = new JPopupMenu();
Action action = new AbstractAction("show trigger location") {

    @Override
    public void actionPerformed(ActionEvent e) {
        JPopupMenu parent = (JPopupMenu) SwingUtilities.getAncestorOfClass(
                JPopupMenu.class, (Component) e.getSource());
        JTable invoker = (JTable) parent.getInvoker();
        Point p = (Point) invoker.getClientProperty("popupTriggerLocation");
        String output = p != null ? "row/col: " 
             + invoker.rowAtPoint(p) + "/" + invoker.columnAtPoint(p) : null; 
        System.out.println(output);
    }
};
popup.add(action);
popup.add("dummy2");
table.setComponentPopupMenu(popup);

+1 ....,请火拼战争不能看到那里重写AWTEventListener的内容 :-) - mKorbel
@mKorbel... 你为什么期望在我的回答中看到AWTEventListener?或者你是什么意思,又一次一无所知 :-) - kleopatra
您可能需要使用 event != null && event.isPopupTrigger() - Joshua Goldberg

3
@MadProgrammer提出的getPopupLocation方法看起来很有前途,但我无法弄清楚如何在表格和actionEvent之间传递信息...
我通过确保在右键单击行时选择该行来解决了这个问题->由于弹出菜单阻止了行的选择,因此您可以添加一个鼠标侦听器,以确保无论按下哪个点击(左键或右键),都会选择该行。
aTable.addMouseListener(new MouseAdapter() {
    @Override
    public void mousePressed(MouseEvent e) {
        int r = aTable.rowAtPoint(e.getPoint());
        if (r >= 0 && r < clt.getRowCount()) {
            aTable.setRowSelectionInterval(r, r);
        } else {
            aTable.clearSelection();
        }
    }
});

这意味着在 rightClickMenuItem 的动作监听器中,你可以获取表格的选定单元格/行。
rightClickMenuItem.addActionListener(new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        aTable.get details about the selected one....
    }
});

太简单了!感谢大家的帮助。


经过再次思考(和测试)...原来的mouseReleased可能是一种笔误,编辑看起来还是可以的。对于造成的麻烦,非常抱歉。 - kleopatra

0

JTable有方法

int row = rowAtPoint(p);
int col = columnAtPoint(p);

因此,传递 MouseEvent 的点并使用这些值。

添加一个 MouseListener 并将最后一次右键单击的点存储在某个地方。


可以使用 SwingUtilities.convertToScreen() 将 JPopupMenu 转换为 JTable 坐标系。 - StanislavL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接