Posted on 2010-09-13 10:32
TWaver 阅读(2347)
评论(0) 编辑 收藏
做ERP或财务软件的朋友知道,中国式的凭证录入界面需要一些特殊的显示效果:录入金额的单元格要显示一些数字分割线。估计这个风格来自老式的手工记账本,因为我还隐约的记得当年从生产队仓库里面偷来的账本就是这个样子滴。为了继续与“Swing很丑”的偏见做斗争,持续弘扬Java的创新精神以及“除了老婆一切都可共享”的Share宗旨,这里特意用Swing写了一个小例子,实现“中国式”的凭证录入界面。

这里面主要用到了Swing Table的Renderer和Editor这两个机制,也是Swing比较有代表性的技术,大家都不陌生。对于熟悉这个机制的童鞋来说,本文实在没什么新意。这里也就不啰嗦废话了,直奔主题,点到为止,然后上代码。
用下面代码设置table一个列的renderer和editor:
1
table.getColumnModel().getColumn(2).setCellRenderer(new MoneyRenderer());
2
table.getColumnModel().getColumn(2).setCellEditor(new MoneyEditor());
在renderer中,首先paint纵向的竖线,然后在paint正常的单元格内容。
1
@Override
2
public void paintChildren(Graphics g)
{
3
Graphics2D g2d = (Graphics2D) g;
4
painter.paint(this, g2d, null);
5
super.paintComponent(g);
6
}
其中,painter是一个封装好的用来画竖线的类。里面说道:
1
public class LinePainter
{
2
3
private Stroke normalStroke = new BasicStroke(1);
4
private Stroke thickStroke = new BasicStroke(1);
5
private Color normalColor = Color.lightGray;
6
private Color tickColor = Color.cyan.darker();
7
private Color decimalColor = Color.red;
8
9
public void paint(JComponent component, Graphics2D g, Color lineColor)
{
10
g.setColor(Color.gray);
11
g.setFont(component.getFont());
12
Rectangle2D bounds = g.getFontMetrics().getStringBounds("0", g);
13
int unitWidth = (int) bounds.getWidth();
14
15
int x = component.getWidth();
16
int rightGap = 0;
17
if (component.getInsets() != null)
{
18
rightGap = component.getInsets().right;
19
}
20
if (component.getBorder() != null)
{
21
rightGap = rightGap + component.getBorder().getBorderInsets(component).right;
22
}
23
if (component instanceof JTextComponent)
{
24
JTextComponent textComponent = (JTextComponent) component;
25
Insets insets = textComponent.getMargin();
26
rightGap = rightGap + insets.right;
27
rightGap = rightGap + 2;
28
}
29
30
x = x - rightGap;
31
32
int index = 0;
33
while (x > unitWidth * 2)
{
34
x = x - unitWidth;
35
if (index == 1)
{
36
g.setStroke(thickStroke);
37
g.setColor(decimalColor);
38
} else
{
39
if ((index - 1) % 3 == 0)
{
40
g.setColor(tickColor);
41
} else
{
42
g.setColor(normalColor);
43
}
44
g.setStroke(normalStroke);
45
}
46
g.drawLine(x, 0, x, component.getHeight());
47
index++;
48
}
49
if (lineColor != null)
{
50
g.setColor(lineColor);
51
g.setStroke(this.normalStroke);
52
g.drawLine(0, component.getHeight() - 1, component.getWidth(), component.getHeight() - 1);
53
}
54
}
55
}
很简单,就一个paint函数,画纵向的彩条线而已。注意间距、字体等的考虑。
为了在编辑期间也能显示纵向线条,所以要定制editor,且重写TextField的paint,先画线条,再super正常的内容paint:
1
@Override
2
public void paint(Graphics g)
{
3
Graphics2D g2d = (Graphics2D) g;
4
painter.paint(this, g2d, Color.red);
5
super.paint(g);
6
}
这样,整个程序就结束了。稍作修改,加上输入格式检查、汇率转换等东西,相信可以很容易的用在你家的ERP或者财务软件上。
给几个家庭作业:
1、这张凭证记录了什么业务活动的发生?
2、为什么“库存商品”一栏的金额在“借方”,而“银行现金”一栏的金额在“贷方”?
3、为什么“进项税额”的金额是17元?
如果能随口回答这几个问题,说明你不仅仅是个优秀的程序员,还是个优秀的财务;至少做个出纳没问题!等咱写不动程序了,去工厂应聘一下出纳吧,没准能成!