1

最近、BigDecimal 変数にバインドするのに最適な Swing コンポーネントはどれかを尋ねました (特定の編集プロパティを使用)。標準の Swing コンポーネントのどれも私に完全に適していないことがわかりました。また、私が見つけたサードパーティの Swing コンポーネント ライブラリもそうではありませんでした。そこで、独自の Swing コンポーネントを作成することにしました。

コンポーネントの説明:

JTextFieldまたはJFormattedTextFieldを拡張したいので、新しいコンポーネントをBigDecimal変数に簡単にバインドできます。

コンポーネントには、カスタマイズ可能なスケール長さのプロパティがあります。

行動:

コンポーネントが描画されると、その右側に小数点とスケール桁のスペースのみが表示されます。

コンポーネントがフォーカスを受け取ると、キャレットは小数点の左に配置する必要があります。ユーザーが数字を入力すると (その他の文字は無視されます)、キャレットの左側に数字が表示されます。長さ-スケールの数字のみが受け入れられ、入力された他の数字は整数部分がいっぱいになるため無視されます。ユーザーが小数点を入力するたびに、キャレットは小数点の右側に移動します。入力された次の数値は小数部に表示されます。スケール番号のみが考慮され、入力された他の数値は小数部がいっぱいであるため無視されます。さらに、ユーザーが小数点以下の数字を入力すると、桁区切り記号が表示されます。

また、コンポーネントをJTableのセル エディタとして使用できるようにしたいと考えています(2 回コーディングする必要はありません)。

コンポーネントで getValue() メソッドを呼び出すと、入力した数値を表す BigDecimal が生成されます。


独自の Swing コンポーネントを作成したことはありません。標準品はほとんど使っていません。したがって、説明されているコンポーネントの作成に関する優れたチュートリアル/情報/ヒントをいただければ幸いです。これは私がこれまでに持っている唯一のものです。

前もって感謝します。

4

2 に答える 2

3

あなたが引用したGrouchnikovの記事は気に入っていますが、UI デリゲートを変更する必要があるかどうかはわかりません。これは不変オブジェクトのビューになるため、継承よりも構成を優先します。この例に見られるように、私はあなたが説明するコンポーネントをレンダラーであると考える傾向があります。またはを追加して、必要な検証を取得できます。InputVerifierDocumwntListener

JFormattedTextField補遺:とを使用する例を次に示しますMaskFormatter。縮尺と長さに合わせて書式マスクを調整する必要があります。

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);
            }
        });
    }
}
于 2010-03-24T21:07:39.100 に答える
2

好きなコンポーネントを使用し、KeyListener を登録して、動作に合わせて文字を拒否します。getValue() と setValue を追加して、BiDecimal やその他のメソッドを簡単に取得/設定すると、すべての描画が任意の JTextComponent によって提供されます。

于 2010-03-24T21:09:36.950 に答える