简体   繁体   English

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

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

I have tried to keep my JTable 's tight and secure, making only editable columns editable via isCellEditable() . 我试图保持我的JTable的严密性和安全性,只通过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). 我可以让单元格可以编辑,而不是对它们在setValueAt()进行的任何编辑做任何事情(因此当编辑器退出时它会恢复原始值)。 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? 是否有一种简单有效的方法可以将JTextField用作单元格编辑器,以允许在编辑器中选择文本,但不可编辑?

I tried this override on my JTable below, but I don't think I'm looking for the right "instanceof" object. 我在下面的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());
        }
    }
}

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. 然后,您将使用Ctrl + C复制所选文本。 Or you could even add a popup menu to the text field and add a Copy menu item. 或者您甚至可以在文本字段中添加弹出菜单并添加“ Copy菜单项。

"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. 您可以使用MouseListener ,并在双击时,以编程方式将单元格的内容复制到剪贴板。 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) {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM