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

tmn*_*tmn 6 java swing jtable jtextfield tablecelleditor

我试图保持我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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

cam*_*ckr 8

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

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

JTextField tf = new JTextField();
tf.setEditable(false);
DefaultCellEditor editor = new DefaultCellEditor( tf );
table.setDefaultEditor(Object.class, editor);
Run Code Online (Sandbox Code Playgroud)

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


Pau*_*tha 7

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

您可以使用a 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);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

这是一个完整的例子:

在此输入图像描述

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) {
    }
}
Run Code Online (Sandbox Code Playgroud)