Приветствуются советы по созданию собственного компонента Swing.

StackOverflow https://stackoverflow.com/questions/2511270

  •  22-09-2019
  •  | 
  •  

Вопрос

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

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

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

Компонент будет иметь настраиваемый шкала и длина характеристики.

Поведение:

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

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

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

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


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

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

Это было полезно?

Решение

мне нравится Гручников статью, которую вы цитировали, но я не уверен, что вы захотите изменить делегат пользовательского интерфейса.Поскольку это будет представление неизменяемого объекта, я бы предпочел композицию наследованию.Я склонен думать о компоненте, который вы описываете, как о средство визуализации, как видно в этом пример.Вы можете добавить 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);
            }
        });
    }
}

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top