当前位置: 首页 > 面试题库 >

欢迎创建我的Swing组件的建议

姬捷
2023-03-14
问题内容

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

我想扩展JTextField或JFormattedTextField,因此我的新组件可以轻松地绑定到BigDecimal变量。

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

行为:

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

当组件获得焦点时,插入号应位于左小数点的位置。当用户键入数字(忽略任何其他字符)时,它们出现在插入符号的左侧,仅接受 长度 - 刻度
数字,而键入的任何其他数字将被忽略,因为整数部分已满。用户每次键入小数点时,插入记号都将移动到小数点的右侧。以下键入的数字显示在小数部分,由于小数部分已满,因此仅将
刻度 数字视为任何其他键入的数字。此外,当用户键入小数点后的数字时,应出现千位分隔符。

我还希望能够使用的组件作为一个单元编辑器在一个JTable中(而不必代码两次)。

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

我从未创建过自己的Swing组件。我几乎没有用过标准的。因此,对于创建上述组件的任何不错的教程/信息/提示,我将不胜感激。这是我到目前为止唯一的一件事。

提前致谢。


问题答案:

我喜欢您引用的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);
            }
        });
    }
}


 类似资料:
  • 问题内容: 我在网上搜索了可拖动的Swing组件的示例,但发现示例不完整或不起作用。 我需要的是一个 Swing组件 ,可以用鼠标将其 拖动 到另一个组件中。在拖动时,它应该 已经改变 了位置,而不仅仅是“跳转”到目的地。 我将感谢没有非标准API的示例。 谢谢。 问题答案: 我提出了一个简单但可行的解决方案,我自己找到了;) 我该怎么办? 当按下鼠标时,我 在屏幕上* 记录了 光标的 位置以及

  • Web 应用程序开发人员可以在 Web 应用程序部署描述文件中定义一个称为欢迎文件的局部 URI 有序列表。在 Web 应用程序部署描述文件模式中描述了部署描述文件中欢迎文件列表的语法。 这种机制的目的是,当一个对应到 WAR文件中一个目录条目的请求 URI没有映射到一个 Web 组件时,允许部署者为容器用于添加 URI 指定局部URI 有序列表。这种请求被认为是有效的局部请求。 通过下面常见的例

  • 该站点的目标是成为 Jekyll 的全面指南。包括一些内容如:搭建和运行你的站点、创建以及管理内容、定制站点的展现和外观、在不同的环境中发布、以及参与到 Jekyll 将来的开发的一些建议。 Jekyll 究竟是什么? Jekyll 是一个简单的博客形态的静态站点生产机器。它有一个模版目录,其中包含原始文本格式的文档,通过一个转换器(如 Markdown)和我们的 Liquid 渲染器转化成一个完

  • 欢迎来到 Libra 开发者站点! Libra 的使命是建立一套简单的全球货币和金融基础设施,为数十亿人服务。 The world truly needs a reliable digital currency and infrastructure that together can deliver on the promise of “the internet of money.” Securi

  • Hyperf 官方提供了工具来快速创建组件包。 # 创建适配 Hyperf 最新版本的组件包 composer create-project hyperf/component-creater your_component dev-master # 创建适配 Hyperf 1.1 版本的组件包 composer create-project hyperf/component-creater you

  • 本文向大家介绍Ionic2创建App启动页左右滑动欢迎界面,包括了Ionic2创建App启动页左右滑动欢迎界面的使用技巧和注意事项,需要的朋友参考一下 摘要: 每个有逼格的App在第一次启动时都有一个欢迎界面,通常是几个单页面或者带动画的单页面滑动到最后一页有个启动的按钮,本文将使用Ionic2来创建,So easy! 效果如下 本文例子和上图稍有不同,主要功能如下: 每滑动一下展示一张全屏图片;