6 Font f = new Font("Serif",0, 100);
7 g.setFont(f);
8 FontMetrics fm = getFontMetrics(f);
9 String s = "HelloWorld";
10 int x = 5;
11 int y = 5;
12
13 for (int i = 0; i < s.length(); i++) {
14 char c = s.charAt(i);
15 int h = fm.getHeight();
16 int w = fm.charWidth(c);
17 System.out.printf("Letter = %c\t Width = %d\t Height = %d\n",c,w,h);
18 g.drawRect(x, y, w, h);
19 g.drawString(String.valueOf(c), x, y + h);
20 x = x + w;
21 }
22 }
23 public static void main(String[] args) {
24 JFrame frame = new JFrame();
25 frame.setTitle("Draw Char one by one");
26 frame.addWindowListener(new WindowAdapter() {
27 public void windowClosing(WindowEvent e) {
28 System.exit(0);
29 }
30 });
31 frame.setContentPane(new MyTest());
32 frame.setSize(600, 400);
33 frame.setVisible(true);
34 }
35 }
9) 通过TextLayout和LineBreakMeasurer对象绘制多行文本:如果当前的文本数据是由很多的字符构成,同时当前Graphics设置的字体尺寸也比较大,那么我们就无法在一行内显示所有的文本,超出显示组件宽度的文本将不会在屏幕上被渲染出来。为了让所有的文本都能够在当前组件中显示,我们就需要在渲染即将超出屏幕宽度之前,折行显示后面的文本信息。这里一个比较关键的技术点是我们如何获知在一定宽度内可以显示的字符数量。在Java 2D中我们可以通过TextLayout和LineBreakMeasurer来帮助我们完成这样的工作。
1 public class MyTest extends JPanel {
2 public void paintComponent(Graphics g) {
3 super.paintComponent(g);
4 Graphics2D g2 = (Graphics2D) g;
5 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING
6 , RenderingHints.VALUE_ANTIALIAS_ON);
7 String s = "A guide to architecting, designing, and building distributed " +
8 "applications with Windows Communication Foundation Windows " +
9 "Communication Foundation is the .NET technology that is used " +
10 "to build service-oriented applications, exchange messages in " +
11 "various communication scenarios, and run workflows.";
12 //1. 用多行字符串构造AttributedString,并设置初始化字体
13 AttributedString as = new AttributedString(s);
14 as.addAttribute(TextAttribute.FONT, new Font("serif", Font.PLAIN, 40));
15 //2. 获取文本和属性的迭代器
16 AttributedCharacterIterator aci = as.getIterator();
17 //3. 通过迭代器和Graphics的字体渲染上下文获取断行测量器
18 //该对象可以根据迭代器返回的文本信息和FontMetrics等属性值,再结合当前
19 //Graphics的渲染上下文计算出每行可以显示的文本。
20 LineBreakMeasurer lbm = new LineBreakMeasurer(aci,g2.getFontRenderContext());
21 //4. 结合JPanel的内边属性,计算每行显示的起始x坐标和宽度
22 Insets insets = getInsets();
23 float wrappingWidth = getSize().width - insets.left - insets.right;
24 float x = insets.left;
25 float y = insets.top;
26 //5. 开始计算每行可以显示的字符数量同时渲染本行的字符串。
27 //getPosition()返回当前正在渲染的字符在整个字符串中的索引值。
28 while (lbm.getPosition() < aci.getEndIndex()) {
29 //5.1 Li