assylias
assylias

Reputation: 328923

JTable: override CTRL+C behaviour

I have a JTable set on SINGLE_SELECTION mode, i.e. the user can only select one row at a time. I am trying to override the CTRL+C KeyListener so that it will copy the whole table to the clipboard.

At the moment, I have added a KeyListener to the JTable itself in its constructor:

public MyTable(AbstractTableModel model) {
    super(model);
    getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    addKeyListener(new ExcelClipboardKeyAdapter(this));
}

The KeyListener looks like this:

public class ExcelClipboardKeyAdapter extends KeyAdapter {

    private static final String LINE_BREAK = System.lineSeparator();
    private static final String CELL_BREAK = "\t";
    private static final Clipboard CLIPBOARD = Toolkit.getDefaultToolkit().getSystemClipboard();
    private final JTable table;

    public ExcelClipboardKeyAdapter(JTable table) {
        this.table = table;
    }

    @Override
    public void keyReleased(KeyEvent event) {
        if (event.isControlDown()) {
            if (event.getKeyCode() == KeyEvent.VK_C) { // Copy                        
                copyToClipboard();
                System.out.println("here");
            }
        }
    }

    private void copyToClipboard() {
        int numCols = table.getColumnCount();
        int numRows = table.getRowCount();
        StringBuilder excelStr = new StringBuilder();
        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j < numCols; j++) {
                excelStr.append(escape(table.getValueAt(i, j)));
                if (j < numCols - 1) {
                    excelStr.append(CELL_BREAK);
                }
            }
            excelStr.append(LINE_BREAK);
        }

        StringSelection sel = new StringSelection(excelStr.toString());
        CLIPBOARD.setContents(sel, sel);
    }

    private String escape(Object cell) {
        return (cell == null? "" : cell.toString().replace(LINE_BREAK, " ").replace(CELL_BREAK, " "));
    }
}

However, when I press CTRL+C, the keyreleased method is not called and does not print "here". The content of the clipboard only contains the selected line.

Any ideas would be welcome.

EDIT

Actually it sometimes works a few times then it stops working and copies one row again... weird...

Upvotes: 4

Views: 3807

Answers (2)

kleopatra
kleopatra

Reputation: 51536

moving my comment into an answer:

implement a custom TransferHandler which creates the "excel-transferable" and use that in the table (with dragEnabled == true) - the keybinding as appropriate for the target OS - then is automatically wired

Upvotes: 3

mKorbel
mKorbel

Reputation: 109823

1) use KeyBundings, rather than KeyListener, because there isn't any issues with Focus and setFosusable

2) can you explain for why reason you needed to determine SystemClipboard this way, maybe there is/are another way(s)

Upvotes: 2

Related Questions