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

Java 右键单击复制JTable的单元格值,java,swing,jtable,clipboard,jpopup,Java,Swing,Jtable,Clipboard,Jpopup,我在一个由2列组成的JTable中显示了一些结果 文件-结果 我实现了一个JPopupMenu,它显示一个复制条目,我尝试复制单元格的值,我右键单击了该单元格 filelistTable.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if(SwingUtilities.isRightMouseButton(e))

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

无论如何,这只适用于少数测试。
我是做错了什么还是遗漏了什么?在我看来,似乎该单元格甚至无法正确选择。

有两件事稍有偏差:

  • 在单击中设置componentPopup在鼠标事件序列中太迟(通常在单击之前按下或释放时触发弹出窗口)
  • 该值取自不正确的单元格: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,因为触发点取决于平台。这意味着您需要监视鼠标按下、鼠标松开和鼠标滑动

不,不需要(只是选中:-):显示组件弹出以响应mouseEvent的机制-发生在BasicLookAndFeel.AWTEventHelper中-仅当它是一个弹出触发器时才这样做


再次阅读api文档(昨天应该已经完成;-)可以发现,总是在显示componentPopup之前调用该方法,也就是说,如果通过其他方式(f.i.键盘)触发,也会调用该方法。在这种情况下,事件参数为null,原始代码将崩溃。好的一面是,有了这一保证,所有寻找目标单元的逻辑都可以转移到该方法中。但是没有尝试,因此可能不可行(如果f.i.那么位置应该基于leadRow/ColumnSelection,当时可能尚未完全处理)

您是否收到任何错误?还是该值未能复制到剪贴板?该值大部分时间都未能复制。
ClipboardOwner.lostOwnership
是否被解雇??不太可能,但可能有什么东西取代了内容。另外,
setContents
方法抛出一个
IllegalStateException
。可能值得尝试捕捉这一点,看看这是否可能导致任何问题。7控制台的打印值没有给出正确的值。如果失败了,,始终是最后一次正确复制的尝试。表的默认传输处理程序的默认复制操作有什么问题?请使用
ListSelectionListener
,而不是
鼠标悬停在
上的
飞行点
或…@mKorbel不明白-哪个飞行点和鼠标在哪里经过发挥作用?无论如何,不需要selectionListener,您可以静态查询lead选择(列和行),您应该检查
MouseEvent.isPopupTrigger
,因为触发点取决于平台。这意味着您需要监视
鼠标按下
鼠标松开
鼠标滑动
,不过:P@MadProgrammer不要这样认为:只有当事件是popupTrigger时才会调用getPopupLocation(至少这是我所期望的,没有检查-但可能是实现-在rootPaneUI或BasicLookAndFeel中,忘记-那么糟糕..不,我们有一些信心,不是吗:-)@kleopatra是的,你是对的,没有注意
JTable
中方法的使用。如果你只是使用鼠标侦听器,这仍然是个好主意
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);