Recommendations are welcome when creating my own Swing component.

I recently asked which was the best Swing component to bind to a BigDecimal variable (with some specific editing properties). It turns out that none of the standard Swing components satisfy me completely, as well as the libraries of third-party Swing components that I found there. Therefore, Ive decided to create his own Swing component.

Component Description:

I want to extend a JTextField or JFormattedTextField , so my new component can easily be associated with a BigDecimal variable.

The component will have custom scale and length properties.

Behavior:

When a component is drawn, it shows only the decimal point and space for the scale digits on the right.

When the component receives focus, the caret should be left to the decimal point. Since the user enters numbers (any other character is ignored), they are displayed to the left of the carriage, only scale length numbers are accepted, any other entered number is ignored when the integer part is filled. Each time a user enters a decimal point, the carriage moves to the right side of the decimal point. The following digits are shown in the decimal part: only the scale numbers are considered any other entered number, it is ignored as the decimal part is filled. In addition, thousands of delimiters should be displayed as user numbers left to the decimal point.

I also want to use the component as the Cell Editor in JTable (without having to code it twice).

A call to the getValue () method for the component should give BigDecimal, representing the number just entered.


I have never created my own Swing component; I almost did not use the standard ones. Therefore, I would appreciate a good tutorial / info / tip on creating the described component. This ... this is the only thing I have so far.

Thanks in advance.

+1
source share
2 answers

I like the Grouchnikov you quoted, but I'm not sure if you want to change the UI delegate. Since this will be a look at an immutable object, I would prefer composition over inheritance. I tend to think of the component you are describing as a renderer , as shown in this example . You can add an InputVerifier or DocumwntListener to get the required validation.

Appendix: Here is an example that uses JFormattedTextField and MaskFormatter . You will need to adjust the format mask according to the scale and length.

 public class TableGrid extends JPanel { private DecimalFormat df; private MaskFormatter mf; private JFormattedTextField tf; public TableGrid() { df = new DecimalFormat("0.00"); try { mf = new MaskFormatter("#.##"); } catch (ParseException ex) { ex.printStackTrace(); } tf = new JFormattedTextField(mf); TableModel dataModel = new TableModel(); JTable table = new JTable(dataModel); table.setCellSelectionEnabled(true); table.setRowHeight(32); table.setDefaultRenderer(BigDecimal.class, new DecRenderer(df)); table.setDefaultEditor(BigDecimal.class, new DecEditor(tf, df)); this.add(table); } private static class TableModel extends AbstractTableModel { private static final int SIZE = 4; private BigDecimal[][] matrix = new BigDecimal[SIZE][SIZE]; public TableModel() { for (Object[] row : matrix) { Arrays.fill(row, BigDecimal.valueOf(0)); } } @Override public int getRowCount() { return SIZE; } @Override public int getColumnCount() { return SIZE; } @Override public Object getValueAt(int row, int col) { return matrix[row][col]; } @Override public void setValueAt(Object value, int row, int col) { matrix[row][col] = (BigDecimal) value; } @Override public Class<?> getColumnClass(int col) { return BigDecimal.class; } @Override public boolean isCellEditable(int row, int col) { return true; } } private static class DecRenderer extends DefaultTableCellRenderer { DecimalFormat df; public DecRenderer(DecimalFormat df) { this.df = df; this.setHorizontalAlignment(JLabel.CENTER); this.setBackground(Color.lightGray); this.df.setParseBigDecimal(true); } @Override protected void setValue(Object value) { setText((value == null) ? "" : df.format(value)); } } private static class DecEditor extends DefaultCellEditor { private JFormattedTextField tf; private DecimalFormat df; public DecEditor(JFormattedTextField tf, DecimalFormat df) { super(tf); this.tf = tf; this.df = df; tf.setHorizontalAlignment(JFormattedTextField.CENTER); } @Override public Object getCellEditorValue() { try { return new BigDecimal(tf.getText()); } catch (NumberFormatException e) { return BigDecimal.valueOf(0); } } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { tf.setText((value == null) ? "" : df.format((BigDecimal) value)); if (isSelected) tf.selectAll(); return tf; } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame f = new JFrame("TableGrid"); f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); f.add(new TableGrid()); f.pack(); f.setVisible(true); } }); } } 
+3
source

Use whatever component you like and register a KeyListener to reject characters according to your behavior. Add getValue () and setValue to easily get / set BiDecimal and some other methods, and the whole picture will be provided by any JTextComponent.

+2
source

All Articles