4

我在由 2 列组成的 JTable 中显示了一些结果。

文件 - 结果

我实现了一个 JPopupMenu,它显示了一个复制条目,我尝试复制单元格的值,我在其中右键单击。

filelistTable.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
         if(SwingUtilities.isRightMouseButton(e))
         {
             TablePopupMenu popup = new TablePopupMenu(filelistTable, e.getPoint());
             filelistTable.setComponentPopupMenu(popup);
         }
    }
});

--

    public TablePopupMenu(JTable table, Point p) {

        this.table = table;
        this.p = p;

        JMenuItem mntmKopieren = new JMenuItem("Kopieren");
        mntmKopieren.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                copyCellToClipboard();
            }
        });
        add(mntmKopieren);
    }

    public void copyCellToClipboard()
    {
        int r = table.rowAtPoint(p);
        int c = table.columnAtPoint(p);
        System.out.println(table.getValueAt(table.convertRowIndexToView(r), 
                table.convertRowIndexToView(c)));
        StringSelection entry = new StringSelection(table.getValueAt(table.convertRowIndexToView(r), 
                table.convertRowIndexToView(c)).toString());
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents( entry, this );

    }

无论如何,这只适用于少数测试。我做错了什么或遗漏了什么?在我看来,好像单元格甚至不会被正确选择。

4

1 回答 1

5

有两件事略有不同:

  • 在 mouseEvents 序列中将 componentPopup 设置为 clicked 为时已晚(弹出窗口通常在单击之前发生的按下或释放时触发)
  • 该值取自错误的单元格:JTable 中的所有坐标都在视图坐标系中,将它们转换为视图坐标将完全关闭

也就是说:获取与单元格坐标相关的上下文的支持很差。通常,最好的选择是(下面的代码片段)

  • 覆盖 getPopupLocation(MouseEvent) 并将位置存储在某处
  • 实施弹出/操作以访问该位置

如果失败(应该在行为良好的应用程序中完成),弹出窗口可能由键盘触发:如果是这种情况,您将需要提供一些其他标记(在焦点单元格中)以进行操作。

final String popupLocation = "table.popupLocation";
final JTable table = new JXTable(new AncientSwingTeam()) {

    @Override
    public Point getPopupLocation(MouseEvent event) {
        // event may be null if triggered by keyboard, f.i.
        // thanks to @Mad for the heads up!
        ((JComponent) event.getComponent()).putClientProperty(
                popupLocation, event != null ? event.getPoint() : null);
        return super.getPopupLocation(event);
    }

};
JPopupMenu popup = new JPopupMenu();
Action printLocation = new AbstractAction("print cell") {

    @Override
    public void actionPerformed(ActionEvent e) {
       Point p = (Point) table.getClientProperty(popupLocation);
       if (p != null) { // popup triggered by mouse
           int row = table.rowAtPoint(p);
           int column = table.columnAtPoint(p);
           LOG.info("" + table.getValueAt(row, column)); 
       } else { // popup triggered otherwise
           // could choose f.i. by leadRow/ColumnSelection
           ...
       }
    }

};
popup.add(printLocation);
table.setComponentPopupMenu(popup);

编辑(由 Mad 的评论触发):

您应该检查 MouseEvent.isPopupTrigger,因为触发点取决于平台。这确实意味着您需要监视 mousePressed、mouseReleased 和 mouseClicked

不,这不是必需的(刚刚检查过:-):显示 componentPopup 以响应 mouseEvent 的机制 - 发生在 BasicLookAndFeel.AWTEventHelper 中 - 只有当它popupTrigger 时才会这样做。

通过再次阅读 api 文档(昨天应该完成 ;-),事实证明该方法总是在显示 componentPopup 之前调用,如果通过其他方式触发,fi 键盘也是如此。在这种情况下,事件参数为空 - 原始代码会崩溃。从好的方面来说,有了这个保证,所有寻找目标细胞的逻辑都可以转移到那个方法中。虽然没有尝试,所以它可能不可行(如果那时该位置应该基于当时可能尚未完全处理的leadRow / ColumnSelection)

于 2012-09-19T11:14:51.427 回答