4

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...

Mwiza
  • 7,780
  • 3
  • 46
  • 42
assylias
  • 321,522
  • 82
  • 660
  • 783
  • actually, just checked: the default already has a plaintextflavour with tabs separating the cells and line-breaks (that is "\n") separating the rows - so, do you really need the _system_ separator? Can't excel handle the single linebreak on import? – kleopatra Feb 28 '12 at 15:47
  • @kleopatra Having a look now. Thanks for the idea. – assylias Feb 28 '12 at 15:54
  • @kleopatra Works like a charm, probably better than the KeyBindings way. Feel free to create an answer if you want to. – assylias Feb 28 '12 at 16:23

2 Answers2

3

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

kleopatra
  • 51,061
  • 28
  • 99
  • 211
2

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)

mKorbel
  • 109,525
  • 20
  • 134
  • 319