右键单击复制JTable的单元格值

时间:2012-09-19 09:23:07

标签: java swing jtable clipboard jpopup

我在一个由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 );

    }

无论如何,这仅适用于少量测试。 我做错了什么或丢失了什么?在我看来,好像细胞甚至无法正确选择。

1 个答案:

答案 0 :(得分:5)

两件事略显偏离:

  • 在clickEvents中设置componentPopup在mouseEvents的序列中为时已晚(弹出窗口通常在按下或释放时触发,在点击之前发生)
  • 该值取自不正确的单元格: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时才会这样做。 / p>

通过阅读api doc(应该在昨天;-)再次进行,事实证明该方法在显示componentPopup之前被称为始终,即使用其他方式f.i触发也是如此。键盘。在这种情况下,事件参数为空 - 原始代码会被破坏。从好的方面来说,通过这种保证,找到目标细胞的所有逻辑都可以转移到该方法中。没试过,所以它可能不可行(如果那时位置应该基于当时可能尚未完全处理的leadRow / ColumnSelection)