我试图保持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());
}
}
}
答案 0 :(得分:8)
然而,我的客户坚持要求他们双击一个单元格,以便他们可以复制其内容,即使它是只读的。
创建一个使用只读文本字段的自定义编辑器:
JTextField tf = new JTextField();
tf.setEditable(false);
DefaultCellEditor editor = new DefaultCellEditor( tf );
table.setDefaultEditor(Object.class, editor);
使用键盘或鼠标选择要复制的文本。然后,您将使用Ctrl + C复制所选文本。或者您甚至可以在文本字段中添加弹出菜单,并添加Copy
菜单项。
答案 1 :(得分:7)
“然而,我的客户坚持他们想要双击一个单元格,以便他们可以复制其内容,即使它是只读的”
您可以使用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) {
}
}