欢迎创建我自己的Swing组件的建议 [英] Advice welcomed on creating my own Swing component

查看:123
本文介绍了欢迎创建我自己的Swing组件的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我问哪个是最好的Swing组件来绑定到BigDecimal变量(具有一些特定的编辑属性)。事实证明,没有一个标准的Swing组件完全适合我,也没有找到我发现的第三方Swing组件库。所以我决定创建自己的Swing组件。

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 components suit me completely, nor did the third-party Swing component libraries I've found out there. So I’ve decided to create my own Swing component.

我想扩展< a href =http://java.sun.com/javase/6/docs/api/javax/swing/JTextField.html\"rel =nofollow noreferrer> JTextField 或 JFormattedTextField ,因此我的新组件可以轻松绑定到 BigDecimal 变量。

I want to extend JTextField or JFormattedTextField, so my new component can be easily bound to a BigDecimal variable.

该组件将具有可自定义的比例长度属性。

The component will have customizable scale and length properties.

绘制组件时,它只显示右侧 scale 数字的小数点和空格。

When the component is drawn, it shows only the decimal point and space for scale digits to its right.

当组件获得焦点时,插入符号应位于小数点左侧。当用户键入数字(忽略任何其他字符)时,它们显示在插入符的左侧,只接受 length - scale 数字,任何其他键入的数字都将被忽略为整数部分已满。每当用户键入小数点时,插入符号移动到小数点的右侧。键入的以下数字显示在小数部分,只有 scale 数字被认为是任何其他数字类型被忽略,因为小数部分已满。此外,当用户键入小数点后的数字时,应显示千位分隔符。

When the component receives focus the caret should be positioned left to the decimal point. As the user types numbers (any other character is ignored) they appear to the left of the caret, only lengthscale numbers are accepted, any other number typed is ignored as the integer portion is full. Any time the user types the decimal point the caret moves to the right side of the decimal point. The following numbers typed are shown in the decimal part, only scale numbers are considered any other number typed is ignored as the decimal portion is full. Additionally, thousand separators should appear as the user types numbers left to the decimal point.

我还希望能够将该组件用作单元格编辑器中的 JTable (无需编码两次)。

I also want to be able to use the component as a Cell Editor in a JTable (without having to code it twice).

在组件上调用getValue()方法应该产生代表刚刚输入的数字的BigDecimal。

Invoking a getValue() method on the component should yield the BigDecimal representing the number just entered.

我从未创建过自己的Swing组件;我几乎没有使用标准的。所以我很感激有关创建所描述组件的任何好的教程/信息/提示。 是我唯一的选择到目前为止。

I’ve never created my own Swing component; I’ve barely used the standard ones. So I would appreciate any good tutorial/info/tip on creating the component described. This is the only thing I've got so far.

提前致谢。

推荐答案

我喜欢你的 Grouchnikov 文章引用,但我不确定你是否想要更改UI委托。因为这将是一个不可变对象的视图,我赞成组合而不是继承。我倾向于将您描述的组件视为渲染器,如示例。您可以添加 InputVerifier DocumwntListener 以获得所需的验证。

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.

附录:这是一个使用<$的示例c $ c> JFormattedTextField 和 MaskFormatter 。您需要调整格式掩码以匹配您的比例和长度。

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

这篇关于欢迎创建我自己的Swing组件的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆