Domanda

ho chiesto che era il migliore componente Swing per bind a una variabile BigDecimal (con alcune particolari proprietà di modifica). Si scopre che nessuno dei componenti Swing standard di me soddisfare completamente, né le librerie di componente Swing di terze parti che ho trovato là fuori. Così ho deciso di creare il mio componente Swing.

Descrizione dei componenti:

voglio estendere JTextField o JFormattedTextField , quindi il mio nuovo componente può essere facilmente associato a un BigDecimal variabile.

Il componente avrà personalizzabile scala e lunghezza Proprietà.

Comportamento:

Quando il componente viene disegnato, mostra solo il punto decimale e lo spazio per scala cifre a sua destra.

Quando il componente viene attivato il cursore deve essere posizionato a sinistra per il punto decimale. Come i numeri utente digita (qualsiasi altro carattere viene ignorato) che appaiono alla sinistra del punto di inserimento, solo lunghezza - scala i numeri sono accettati, qualsiasi altro numero digitato viene ignorato come la parte intera è piena. Ogni volta che l'utente digita il punto decimale il cursore si sposta verso destra del punto decimale. I seguenti numeri digitati sono riportati nella parte decimale, solo scala i numeri sono considerati qualsiasi altro numero digitato viene ignorato come la parte decimale è pieno. Inoltre, separatori delle migliaia dovrebbero apparire come i numeri utente digita a sinistra per il punto decimale.

Voglio anche essere in grado di utilizzare il componente come Cell Editor in un JTable (senza dover codificare due volte).

Invocare un metodo getValue () sul componente dovrebbe dare il BigDecimal che rappresenta il numero appena inserito.


Non ho mai creato il mio componente Swing; Ho a malapena usato quelle standard. Così Gradirei qualsiasi buon tutorial / informazioni / punta sulla creazione del componente descritto. Questa è l'unica cosa che ho 've ha ottenuto finora.

Grazie in anticipo.

È stato utile?

Soluzione

Mi piace il Grouchnikov articolo citato, ma non sono sicuro che si vorrebbe cambiare il delegato UI. Dato che questa sarà una vista di un oggetto immutabile, sarei favorevole composizione per l'eredità. Tendo a pensare del componente si descrive in termini di essere un renderer , come si vede in questo . È possibile aggiungere un InputVerifier o DocumwntListener per ottenere la convalida che si desidera.

Addendum: Ecco un esempio che utilizza JFormattedTextField ed un MaskFormatter . Avrai bisogno di regolare la maschera di formato per abbinare la vostra scala e lunghezza.

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);
            }
        });
    }
}

Altri suggerimenti

Usare qualsiasi componente che si piace e registra un KeyListener a respingere caratteri per abbinare il vostro behaviour.Add un getValue () e setValue per ottenere / impostare facilmente un BiDecimal e alcuni altri metodi e tutta la pittura sarà fornito da qualsiasi JTextComponent.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top