欢迎就创建我自己的 Swing 组件提出建议
-
22-09-2019 - |
题
最近 我问 这是绑定到 BigDecimal 变量的最佳 Swing 组件(具有一些特定的编辑属性)。事实证明,没有一个标准 Swing 组件完全适合我,我在那里找到的第三方 Swing 组件库也不适合。所以我决定创建我自己的 Swing 组件。
组件说明:
我想延长 文本字段 或者 JFormattedTextField, ,所以我的新组件可以轻松绑定到 大十进制 多变的。
该组件将具有可定制的 规模 和 长度 特性。
行为:
绘制组件时,只显示小数点和空格 规模 其右侧的数字。
当组件获得焦点时,插入符号应位于小数点左侧。当用户键入数字时(任何其他字符都会被忽略),它们只会出现在插入符号的左侧 长度 – 规模 接受数字,输入的任何其他数字都将被忽略,因为整数部分已满。每当用户键入小数点时,插入符号都会移动到小数点的右侧。以下输入的数字只显示小数部分 规模 数字被视为输入的任何其他数字都将被忽略,因为小数部分已满。此外,当用户键入小数点后的数字时,应显示千位分隔符。
我还希望能够将该组件用作 单元格编辑器 在一个 J表 (无需编码两次)。
在组件上调用 getValue() 方法应生成表示刚刚输入的数字的 BigDecimal。
我从未创建过自己的 Swing 组件;我几乎没用过标准的。因此,我将不胜感激有关创建所描述组件的任何好的教程/信息/提示。 这 这是我迄今为止唯一拥有的东西。
提前致谢。
解决方案
我喜欢 格鲁奇尼科夫 您引用的文章,但我不确定您是否想要更改 UI 委托。由于这将是一个不可变对象的视图,因此我更喜欢组合而不是继承。我倾向于认为你所描述的组件是 渲染器, ,正如在此看到的 例子. 。您可以添加一个 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拒绝字符,以配合您behaviour.Add一个的getValue()的setValue获取/容易设置BiDecimal和其他一些方法,所有的画会被任何的JTextComponent提供。