使JTable单元格编辑器值可选,但不可编辑?

我试图保持我的JTable的严密性和安全性,只通过isCellEditable()编辑可编辑的列。 但是,我的客户坚持要求他们双击单元格以便他们可以复制其内容,即使它是只读的。 我可以让单元格可以编辑,而不对它们在setValueAt()进行的任何编辑做任何事情(因此当编辑器退出时它会恢复为原始值)。 但我不希望这个应用程序感觉如此自由。 是否有一种简单有效的方法可以将JTextField用作单元格编辑器,以允许在编辑器中选择文本,但不可编辑?

我在下面的JTable上尝试了这个覆盖,但我认为我没有找到正确的“instanceof”对象。

 @Override public TableCellEditor getDefaultEditor(Class columnClass) { if (super.getDefaultEditor(columnClass) instanceof JTextField) { JTextField jTextField = new JTextField(); jTextField.setEditable(false); return (TableCellEditor) jTextField; } if (columnClass == null) { return null; } else { Object editor = defaultEditorsByColumnClass.get(columnClass); if (editor != null) { return (TableCellEditor)editor; } else { return getDefaultEditor(columnClass.getSuperclass()); } } } 

但是,我的客户坚持要求他们双击单元格以便他们可以复制其内容,即使它是只读的。

创建一个使用只读文本字段的自定义编辑器:

 JTextField tf = new JTextField(); tf.setEditable(false); DefaultCellEditor editor = new DefaultCellEditor( tf ); table.setDefaultEditor(Object.class, editor); 

使用键盘或鼠标选择要复制的文本。 然后,您将使用Ctrl + C复制所选文本。 或者您甚至可以在文本字段中添加弹出菜单并添加“ Copy菜单项。

“但是,我的客户坚持他们想要双击一个单元格,以便他们可以复制其内容,即使它是只读的”

您可以使用MouseListener ,并在双击时,以编程方式将单元格的内容复制到剪贴板。 就像是:

 table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { System.out.println("double click"); Point p = e.getPoint(); int row = table.rowAtPoint(p); int col = table.columnAtPoint(p); Object value = table.getValueAt(row, col); StringSelection stringSelection = new StringSelection(value.toString()); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(stringSelection, ProgrammaticCopyDemo.this); } } }); 

这是一个完整的例子:

在此处输入图像描述

 import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*; import java.io.IOException; import javax.swing.*; import javax.swing.table.DefaultTableModel; import javax.swing.text.JTextComponent; public class ProgrammaticCopyDemo implements ClipboardOwner { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new ProgrammaticCopyDemo(); } }); } public ProgrammaticCopyDemo() { JTable table = getTable(); addCopylistenerToTable(table); JTextArea area = new JTextArea(3, 20); addPasteListenerToArea(area); JFrame frame = new JFrame(); frame.add(new JScrollPane(table)); frame.add(area, BorderLayout.PAGE_END); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); frame.setVisible(true); } private void addPasteListenerToArea(final JTextComponent component) { JPopupMenu menu = new JPopupMenu(); menu.add(new AbstractAction("Paste") { public void actionPerformed(ActionEvent e) { String copiedContent = getClipboardContents(); int caretPosition = component.getCaretPosition(); try { component.getDocument().insertString(caretPosition, copiedContent, null); } catch (Exception ex) { ex.printStackTrace(); } } private String getClipboardContents() { String result = ""; Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable contents = clipboard.getContents(null); boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor); if (hasTransferableText) { try { result = (String) contents.getTransferData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException | IOException ex) { System.out.println(ex); ex.printStackTrace(); } } return result; } }); component.setComponentPopupMenu(menu); } private void addCopylistenerToTable(final JTable table) { table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { System.out.println("double click"); Point p = e.getPoint(); int row = table.rowAtPoint(p); int col = table.columnAtPoint(p); Object value = table.getValueAt(row, col); StringSelection stringSelection = new StringSelection(value.toString()); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(stringSelection, ProgrammaticCopyDemo.this); } } }); } private JTable getTable() { String[][] data = { {"Hello", "World"}, {"Stack", "Overflow"}, {"Foo", "Bar"} }; String[] cols = {"Col", "Col"}; DefaultTableModel model = new DefaultTableModel(data, cols) { @Override public boolean isCellEditable(int row, int col) { return false; } }; return new JTable(model) { @Override public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } }; } @Override public void lostOwnership(Clipboard clipboard, Transferable contents) { } }