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

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

组件说明:

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

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

行为:

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

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

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

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


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

提前致谢。

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

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

 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提供。