Приветствуются советы по созданию собственного компонента Swing - PullRequest
1 голос
/ 24 марта 2010

Недавно Я спросил , какой компонент Swing был лучшим для привязки к переменной BigDecimal (с некоторыми конкретными свойствами редактирования). Оказывается, что ни один из стандартных компонентов Swing не подходит мне полностью, равно как и сторонние библиотеки компонентов Swing, которые я там обнаружил. Поэтому я решил создать свой собственный компонент Swing.

Описание компонента:

Я хочу расширить JTextField или JFormattedTextField , чтобы мой новый компонент можно было легко связать с переменной BigDecimal .

Компонент будет иметь настраиваемые свойства scale и length .

Поведение:

Когда компонент рисуется, он показывает только десятичную точку и пробел для масштаба цифр справа.

Когда компонент получает фокус, каретка должна быть расположена слева от десятичной точки. Поскольку пользователь вводит числа (любой другой символ игнорируется), они появляются слева от каретки, принимаются только длина - масштаб , любой другой набранный номер игнорируется как целое число часть заполнена Каждый раз, когда пользователь вводит десятичную точку, каретка перемещается в правую часть десятичной точки. Следующие набранные числа показаны в десятичной части, только масштаб числа считаются, любые другие введенные числа игнорируются, так как десятичная часть заполнена. Кроме того, тысячи разделителей должны отображаться как числа, вводимые пользователем с точностью до десятичной точки.

Я также хочу иметь возможность использовать компонент в качестве Редактора ячеек в JTable (без необходимости кодировать его дважды).

Вызов метода getValue () для компонента должен привести к значению BigDecimal, представляющему только что введенное число.


Я никогда не создавал свой собственный компонент Swing; Я едва использовал стандартные. Поэтому я был бы признателен за любой хороший учебник / информацию / совет по созданию описанного компонента. Это - единственное, что у меня есть.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 25 марта 2010

Мне нравится статья Grouchnikov , которую вы цитировали, но я не уверен, что вы захотите изменить делегат пользовательского интерфейса. Поскольку это будет вид неизменного объекта, я бы предпочел композицию наследованию. Я склонен думать о компоненте, который вы описываете, как о рендерере , как видно из этого примера Вы можете добавить InputVerifier или DocumwntListener для получения требуемой проверки.

Приложение: Вот пример, который использует 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);
            }
        });
    }
}
2 голосов
/ 25 марта 2010

Используйте любой компонент, который вам нравится, и зарегистрируйте KeyListener для отклонения символов в соответствии с вашим поведением. Добавьте getValue () и setValue, чтобы легко получить / установить BiDecimal и некоторые другие методы, и вся картина будет предоставлена ​​любым JTextComponent.

...