0

I have a GUI designed as a Form in Netbeans 7.2. I have a JTable with the troublesome behavior. The table model is designed with Right-Click -> Properties -> Model and setting up 1 row and 12 columns with types Long and Double for editable number fields.

enter image description here

Now if I navigate to such a cell which contain e.g. "0.0" and just start typing "123" I get "0.0123" instead of "123". I would like it to work that if you just start typing you start with a blank value - and if the entry is "clicked" then you start editing the cell and whatever you type is inserted at the cursor location.

Can this be done easily?

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
  • 1
    If you provide your TableCellEditor, this shouldn't be too complicated to do. I am not sure to understand the exact behaviour you want to obtain. Usually, what I add is a `selectAll()` on the CellEditor when the edition starts, this way, if you start typing it replaces the current content, but if you click at a particular location in the textfield, the text is appended. – Guillaume Polet May 21 '12 at 10:19
  • So I need to look at the CellEditor? I just currently use the defaults as provided by Netbeans and it has been quite a while since I did table cell stuff in Swing. – Thorbjørn Ravn Andersen May 21 '12 at 10:44

2 Answers2

3

I found https://stackoverflow.com/a/8493016/53897 to work.

The way to add the code, is to right-click the JTable in the Navigator, and choose "Code Customizer". In the line for new javax.swing.JTable() change the drop down box to "custom creation" and you can now edit that snippet including adding the {...@Override public void changeSelection(...)...} needed for this.

Community
  • 1
  • 1
Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
  • 1
    +1 right, code by @camickr for selectAll for Editor is simple great, I'd put selectAll to the invokeLater(), for safest workaround – mKorbel May 21 '12 at 12:18
2
  • whats wrong with standard Swing JTable and DefaultTableModel

  • sure there are missing some ideas for productions code (make the things better)..., selectAll for Editor, cell alingment, background, foreground, stripping, font, Look and Feels etc... (most of custom Look and Feels doesn't works correctly with built-in Components pallette in Netbeans Swing Framework),

  • SwingX have got Components pallette for Netbeans, better and safest way, maybe you have look at ...

enter image description here

import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.table.*;

public class EditorTest {

    private JScrollPane getTableComponent() {
        String[] colNames = {"Stock", "Price", "Shares", "Quantity", "Action", "Action", "Holder"
        };
        final Object[][] data = {{"MSFT", Double.valueOf(12.21), Integer.valueOf(10),
                Integer.valueOf(0), "Buy", "Sell", "Bill"}, {"IBM", Double.valueOf(13.21), Integer.valueOf(12),
                Integer.valueOf(0), "Buy", "Sell", "Tim"}, {"ORACLE", Double.valueOf(21.22), Integer.valueOf(11),
                Integer.valueOf(0), "Buy", "Sell", "Tom"}
        };
        DefaultTableModel model = new DefaultTableModel(data, colNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public Class getColumnClass(int col) {
                return data[0][col].getClass();
            }
        };
        JTable table = new JTable(model);
        TableColumnModel colModel = table.getColumnModel();
        colModel.getColumn(1).setCellRenderer(new DoubleRenderer());
        colModel.getColumn(3).setCellRenderer(new SpinnerRenderer());
        colModel.getColumn(4).setCellRenderer(new ButtonRenderer());
        colModel.getColumn(5).setCellRenderer(new ButtonRenderer());
        colModel.getColumn(3).setCellEditor(new SpinnerEditor());
        colModel.getColumn(4).setCellEditor(new ButtonEditorA(table));
        colModel.getColumn(5).setCellEditor(new ButtonEditorA(table));
        table.setCellSelectionEnabled(true);
        Dimension d = table.getPreferredSize();
        table.setPreferredScrollableViewportSize(d);
        return new JScrollPane(table);
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new EditorTest().getTableComponent());
        f.pack();
        f.setLocation(100, 100);
        f.setVisible(true);
    }
}

class SpinnerEditor extends AbstractCellEditor implements TableCellEditor {

    private static final long serialVersionUID = 1L;
    private SpinnerNumberModel model = new SpinnerNumberModel(0, 0, null, 1);
    private JSpinner spinner = new JSpinner(model);
    private int clickCountToStart = 1;

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        spinner.setValue(((Integer) value).intValue());
        return spinner;
    }

    public Object getCellEditorValue() {
        return (Integer) spinner.getValue();
    }

    @Override
    public boolean isCellEditable(EventObject anEvent) {
        if (anEvent instanceof MouseEvent) {
            return ((MouseEvent) anEvent).getClickCount() >= clickCountToStart;
        }
        return true;
    }

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        return true;
    }

    @Override
    public boolean stopCellEditing() {
        return super.stopCellEditing();
    }

    @Override
    public void cancelCellEditing() {
        super.cancelCellEditing();
    }
}

class ButtonEditorA extends AbstractCellEditor implements TableCellEditor, ActionListener {

    private static final long serialVersionUID = 1L;
    private JTable table;
    private JButton button = new JButton();
    private NumberFormat nf = NumberFormat.getCurrencyInstance();
    private int clickCountToStart = 1;

    public ButtonEditorA(JTable table) {
        this.table = table;
        button.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        StringBuilder sb = new StringBuilder();
        int row = table.getEditingRow();
        int col = table.getEditingColumn();
        //System.out.printf("row = %d  col = %d%n", row, col);
        sb.append((String) table.getValueAt(row, 6));
        sb.append(" has ");
        sb.append(((col == 4) ? "bought " : "sold "));
        sb.append(((Integer) table.getValueAt(row, 3)).toString());
        sb.append(" shares of " + (String) table.getValueAt(row, 0));
        sb.append(" at " + nf.format(((Double) table.getValueAt(row, 1)).doubleValue()));
        stopCellEditing();
        System.out.println(sb.toString());
    }

    public Component getTableCellEditorComponent(JTable table,
            Object value,
            boolean isSelected,
            int row, int column) {
        button.setText(value.toString());
        return button;
    }

    public Object getCellEditorValue() {
        return button.getText();
    }

    @Override
    public boolean isCellEditable(EventObject anEvent) {
        if (anEvent instanceof MouseEvent) {
            return ((MouseEvent) anEvent).getClickCount() >= clickCountToStart;
        }
        return true;
    }

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        return true;
    }

    @Override
    public boolean stopCellEditing() {
        return super.stopCellEditing();
    }

    @Override
    public void cancelCellEditing() {
        super.cancelCellEditing();
    }
}

class SpinnerRenderer implements TableCellRenderer {

    private SpinnerNumberModel model = new SpinnerNumberModel(0, 0, null, 1);
    private JSpinner spinner = new JSpinner(model);

    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        spinner.setValue(((Integer) value).intValue());
        return spinner;
    }
}

class ButtonRendererA implements TableCellRenderer {

    private JButton button = new JButton();

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        button.setText(value.toString());
        return button;
    }
}

class DoubleRenderer extends DefaultTableCellRenderer {

    private static final long serialVersionUID = 1L;
    private NumberFormat nf = NumberFormat.getCurrencyInstance();

    public DoubleRenderer() {
        setHorizontalAlignment(RIGHT);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        setText(nf.format(((Double) value).doubleValue()));
        return this;
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • We just used the Netbeans GUI for as much as we could as there might be non-technical people needing to work with the GUI-part. I appreciate your efforts but do you have a simple "just-do-this" I can use for now? – Thorbjørn Ravn Andersen May 21 '12 at 10:43
  • advantage of GUI Frameworks is very simple to put custom Components (partly override by Framework) to the Framework GUI, disadvantage is bothering with deepest properties, for better GUI by non-technical people needing to knows GUI Framework plus basic methods in the Swing APIs – mKorbel May 21 '12 at 10:57