Advice welcomed on creating my own Swing component

后端 未结 2 421
不思量自难忘°
不思量自难忘° 2020-12-07 00:00

Recently I asked which was the best Swing component to bind to a BigDecimal variable (with some particular editing properties). It turns out that none of the standard Swing

相关标签:
2条回答
  • 2020-12-07 00:30

    Use whatever component you like and register a KeyListener to reject characters to match your behaviour.Add a getValue() & setValue to get/set easily a BiDecimal and some other methods and all the painting will be provided by any JTextComponent.

    0 讨论(0)
  • 2020-12-07 00:36

    I like the Grouchnikov article you cited, but I'm not sure you would want to change the UI delegate. As this will be a view of an immutable object, I'd favor composition over inheritance. I tend to think of the component you describe in terms of being a renderer, as seen in this example. You can add an InputVerifier or DocumwntListener to obtain the validation you want.

    Addendum: Here's an example that uses JFormattedTextField and a MaskFormatter. You'll need to adjust the format mask to match your 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);
                }
            });
        }
    }
    
    0 讨论(0)
提交回复
热议问题