Make JTable cell editor value be selectable, but not editable?

霸气de小男生 提交于 2019-12-06 00:43:41

问题


I have tried to keep my JTable's tight and secure, making only editable columns editable via isCellEditable(). However, my clients are insisting that they want to double click on a cell so they can copy its contents, even if it is read only. I could let the cell be editable and not do anything with any edits they could make in the setValueAt() (so it reverts back to original value when editor exits). But I don't want this application to feel so freeform. Is there an easy effective way to make the JTextField used as the cell editor to allow selecting of text in the editor, but not editable?

I tried this override on my JTable below, but I don't think I'm looking for the right "instanceof" object.

@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());
        }
    }
}

回答1:


However, my clients are insisting that they want to double click on a cell so they can copy its contents, even if it is read only.

Create a custom editor that uses a readonly text field:

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

Use the keyboard or mouse to select the text you want to copy. Then you would then use Ctrl+C to copy the selected text. Or you could even add a popup menu to the text field and add a Copy menu item.




回答2:


"However, my clients are insisting that they want to double click on a cell so they can copy its contents, even if it is read only"

You could just use a MouseListener, and on a double click, programmatically copy the contents of the cell to the clipboard. Something like:

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);
        }
    }
});

Here's a full example:

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) {
    }
}


来源:https://stackoverflow.com/questions/25917580/make-jtable-cell-editor-value-be-selectable-but-not-editable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!