sun在线教材之-java 2d 文本指南-第二课 绘制艺术字

 

 

 

 

Training Index

2D文本指南


第二课: 绘制艺术字

作者: Monica Pawlan
September 1998

翻译: Cherami Liumin
2001年11月

[<<上一课] [目录] [下一课>>]

这一课解释如何使用 java.awt.font.TextLayout 类绘制简单和复杂的艺术字以创建有趣和令人愉快的视觉效果。

  • 绘制一行文本
  • 绘制多行文本
  • 文本倾斜
  • 用图像填充剪切区域
  • 用线条填充剪切区域
  • 用字符填充剪切区域
  • 文本属性和替换图形
  • 练习

绘制一行文本

java.awt.font.TextLayout类可以让你使用字符,字体和属性集创建艺术字。一旦被创建,TextLayout对象就不可编辑,但是它的方法可以让你访问布局、字体、脱字符、选择和点击测试信息。

下面的代码使用FontTextLayoutFontRenderContext 对象绘制一个简单的文本,使用24点Times黑体。TimesB.java 是完整的源代码。

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Helvetica",Font.BOLD, 24);
String s = new String("24 Pont Helvetica Bold");
TextLayout tl = new TextLayout(s, f, frc);
Dimension theSize=getSize();
g2.setColor(Color.green);
tl.draw(g2, theSize.width/30, theSize.height/2);
  • Java.awt.Font 代表系统中可用字体的一个实例。

  • java.awt.TextLayout 代表不可变的艺术字数据。

  • java.awt.font.FontRenderContext 包含绘制文本时需要的正确测量和定位它的信息。

绘制多行文本

你可以用TextLayoutjava.awt.LineBreakMeasurer类绘制一段艺术字。下一个例子使用 LineBreakMeasurer 对象创建并绘制数行文本,文本的布局符合组件的宽度。TextLayoutgetAscentgetDescent方法返回的字体信息被用于定位组件中的行数。文本被作为一个AttributedCharacterIterator存储,因此字体和大小属性可以和文本一起被储存。

LineBreakSample.java是完整的源代码。SampleUtils.java类包含LineBreakSample程序要显示的文本。


注意: LineBreakSample程序支持外语文本。参看第四课: 外语支持获取更多信息。

public class LineBreakSample extends Component {
  private LineBreakMeasurer lineMeasurer;
  private int paragraphStart;
  private int paragraphEnd;
  public LineBreakSample
      (AttributedCharacterIterator paragraph) {
    FontRenderContext frc = 
      SampleUtils.getDefaultFontRenderContext();
    paragraphStart = paragraph.getBeginIndex();
    paragraphEnd = paragraph.getEndIndex();
    lineMeasurer = 
      new LineBreakMeasurer(paragraph, frc);
  }
  public void paint(Graphics g) {
    Graphics2D graphics2D = (Graphics2D) g;
    Dimension size = getSize();
    float formatWidth = (float) size.width;
    float drawPosY = 0;
    lineMeasurer.setPosition(paragraphStart);
    while (lineMeasurer.getPosition() < paragraphEnd) {
       TextLayout layout = 
  lineMeasurer.nextLayout(formatWidth);
       drawPosY += layout.getAscent();
       float drawPosX;
       if (layout.isLeftToRight()) {
        drawPosX = 0;
       }
       else {
         drawPosX = formatWidth - layout.getAdvance();
       }
       layout.draw(graphics2D, drawPosX, drawPosY);
       drawPosY += layout.getDescent() + 
    layout.getLeading();
     }
  }

倾斜文本

你可以从一个提供如何旋转,缩放,移动或者剪切字体的信息的变换对象上创建一个Font对象。下一个例子使用一个剪切变换绘制一个倾斜文本.首先,字符串没有任何变换,然后它被绘制在一个不同的地方。 StillLife.java 是完整的源代码。

  int w = getSize().width;
  int h = getSize().height;
//创建变换
  AffineTransform at = new AffineTransform();
  at.setToTranslation(30, 50);
  AffineTransform fontAT = new AffineTransform();
  fontAT.shear(0.2, 0.0);
//创建字体和文本图层
  FontRenderContext frc = g2.getFontRenderContext();
  Font theFont = new Font("Times", Font.BOLD, w/25);
  String s = new String("Still Life with Text");
  TextLayout tstring = new TextLayout(s, theFont, frc);
  Font theDerivedFont = theFont.deriveFont(fontAT);
  String str = new String("Still Life with Slanted Text");
  TextLayout tstring2 = new TextLayout(str, 
   theDerivedFont, frc);
//绘制普通字符串
  g2.setColor(Color.blue);
  g2.transform(at);
  tstring.draw(g2, (float)0, (float)0);
//绘制倾斜字体字符串
  g2.setColor(Color.green);
  g2.transform(at);
  tstring2.draw(g2, (float)0, (float)0);

用图像填充剪切区域

下一个例子从文本串The Starry Night创建一个剪切区域,然后使用Vincent van Gogh的绘画 The Starry Night填充那个剪切区域。Starry.java是完整的源代码。

The Starry Night by Vincent van Gogh 这个范例代码用Times黑体字符串The Starry Night创建一个文本图层。然后得到TextLayout范围的宽度。范围 包含图层可以绘制的所有象素。

然后它得到文本图层的轮廓并用范围的宽度计算原始图层的X和Y位置。轮廓用于创建一个Shape对象,而Rectangle对象是从Shape对象的范围上创建的。

这时,图形环境的前景颜色被设置为蓝色并且Shape对象被绘制到图形环境。下面的图像和代码片断展示了所发生的事情。

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Times",Font.BOLD,w/10);
String s = new String("The Starry Night");
TextLayout tl = new TextLayout(s, f, frc);
float sw = (float) tl.getBounds().getWidth();
AffineTransform transform = new AffineTransform();
transform.setToTranslation(w/2-sw/2, h/4);
Shape shape = tl.getOutline(transform);
Rectangle r = shape.getBounds();
g2.setColor(Color.blue);
g2.draw(shape);

最后,使用Shape对象在图形环境下建立剪切区域,然后starry.gif 被绘制到该剪切区域,起点在Rectangle对象的左上角(r.xr.y)并且填充矩形对象的整个范围。

g2.setClip(shape);
g2.drawImage(img, r.x, r.y, r.width, r.height, this);

用线条填充剪切区域

为了得到一个稍微不同的效果,下面的例子从文本图层By创建一个剪切区域,该区域用蓝色填充,然后在蓝色剪切区域绘制黄色横线。TextLayoutgetAscent 方法返回的信息用于定位显示的线条。

Clipping.java 是完整的源代码。

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Helvetica",Font.BOLD,w/8);
String s = new String("By");
TextLayout tl = new TextLayout(s, f, frc);
float sw = (float) tl.getBounds().getWidth();
AffineTransform transform = new AffineTransform();
transform.setToTranslation(w/2-sw/2,h/2);
Shape shape = tl.getOutline(transform);
g2.setClip(shape);
g2.setColor(Color.blue);
g2.fill(shape.getBounds());
g2.setColor(Color.yellow);
for (int j = shape.getBounds().y; 
    j < shape.getBounds().y + 
    shape.getBounds ().height; j=j+3) {
  Line2D line = new Line2D.Float( 0.0f, (float) j, 
   (float) w, (float) j);
  g2.draw(line);
}

用字符填充剪切区域

下一个例子从文本图层Vincent van Gogh上创建一个剪切区域,使用蓝色填充,用白色的星号(*)(译注:源代码中实际使用的是加号+)填充该区域,得到蓝天上的白色星星的效果。 TextClipping.java 是完整的源代码。

FontRenderContext frc = g2.getFontRenderContext();
Font f = 
  new Font("Times New Roman Bold",Font.PLAIN,w/8);
String s = new String("Vincent van Gogh");
TextLayout tl = new TextLayout(s, f, frc);
float sw = (float) tl.getBounds().getWidth();
AffineTransform transform = new AffineTransform();
transform.setToTranslation(w/2-sw/2,h-h/6);
Shape shape = tl.getOutline(transform);
g2.setClip(shape);
g2.setColor(Color.blue);
g2.fill(shape.getBounds());
g2.setColor(Color.white);
f = new Font("Helvetica",Font.BOLD,10);
tl = new TextLayout("+", f, frc);
sw = (float) tl.getBounds().getWidth();
Rectangle r = shape.getBounds();
int x = r.x;
int y = r.y;
while ( y < (r.y + r.height+(int) tl.getAscent()) ) {
      tl.draw(g2, x, y);
      if ((x += (int) sw) > (r.x+r.width)) {
      x = r.x;
      y += (int) tl.getAscent();
      }
}

文本属性和替换图形

TextAttribute类定义了文本的属性,因此你可以使用文本属性定义一个Attributed(属性化的)字符串。下一个例子使用文本属性为包含文本The Starry Nightjava.awt.text.AttributedString定义字体和特性替换图像。一个从图像上创建的ImageGraphicAttribute 对象完成这个工作。 MakeImage.java 是完整的源代码。
public void paint(Graphics g) {
  Graphics2D g2;
  g2 = (Graphics2D) g;
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
  g2.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
  Font f = new Font("Times",Font.BOLD, 24);
  AttributedString ats = 
    new AttributedString("The  Starry  Night");
  ImageGraphicAttribute iga = 
    new ImageGraphicAttribute(img, 
    (int) BOTTOM_ALIGNMENT);
  ats.addAttribute(
    TextAttribute.CHAR_REPLACEMENT, iga, 4, 5);
  ats.addAttribute(
    TextAttribute.CHAR_REPLACEMENT, iga, 11, 12);
  ats.addAttribute(TextAttribute.FONT, f, 0, 18);
  AttributedCharacterIterator iter = ats.getIterator();
  FontRenderContext frc = g2.getFontRenderContext();
  tl = new TextLayout(iter, frc);
  g2.setColor(Color.red);
  tl.draw(g2, (float)20, (float)30);
}
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 这是一个Java命令的错误提示,意思是指出了一个未被识别的选项:--add-opens=java.rmi/sun.rmi.transport=all-unnamed。这个选项可能是由于Java版本不兼容或者命令行参数错误导致的。需要检查Java版本和命令行参数是否正确。 ### 回答2: --add-opens选项是用于Java 9及以上版本的JVM中,用于解决一些旧版本Java中的限制性访问问题。该选项可以打开指定的JDK内部模块package,并允许它们暴露给其他代码和模块使用。 在问题中,出现了“unrecognized option”错误,这意味着该选项并没有被识别。通常情况下,这是因为您正在使用的JVM版本过旧,不支持该选项而导致的。 解决该问题的方法是先升级您的JVM到Java 9或以上版本。如果您仍然使用Java 8或更旧的版本,则必须使用其他方法来解决访问限制问题。您可以尝试使用其他选项或设置,如--illegal-access选项作为替代方案。 还有一点要注意的是,--add-opens选项必须被严格控制和使用,并且只应用于特定的JDK内部package。不正确地使用该选项可能导致Java应用程序的安全和稳定性等方面的问题。因此,在使用该选项时,请确保已经仔细检查了您的代码和开发环境,并遵循最佳实践和安全建议。 ### 回答3: 这个问题看起来是关于Java语言和Java Virtual Machine(JVM)的。从错误消息中可以看出,指定的命令选项是--add-opens=java.rmi/sun.rmi.transport=all-unnamed,但是这个选项未被识别。具体来说,这是Java 9和Java 10引入的一个新特性,它允许开发人员在运行库(JRE)中打开Java模块的非公开包以便让其他模块可以访问它们。这个选项的具体含义是:打开java.rmi模块内的sun.rmi.transport包,让所有未命名(未命名意味着不在同一个Java模块)的模块都可以访问它。 但是,如果你得到了“unrecognized option”的错误,这意味着你的Java版本可能不支持这个选项。你可以检查你的Java版本是否在Java 9或者Java 10以上,这是为什么Java会报错的关键。如果你的Java版本太老,那么你需要升级Java来支持这个选项。 如果你的Java版本是在Java 9或者Java 10以上,那么你需要检查你的命令行是否正确。请确保你输入的命令里的选项拼写和格式都正确。如果问题依然存在,那么可能是因为你使用的JVM不允许这个选项。在这种情况下,你可以通过修改JVM的配置来解决问题。需要先确定使用的JVM是哪个,然后去相应的JVM配置文件中添加这个选项即可。不过这个步骤可能需要高级用户完成,需要谨慎操作,以免引发其他不必要的错误。 总之,这个错误消息提示了Java中一个新特性的引入,但是如果你的Java版本太老或者使用的JVM不支持这个特性,就会出现错误。如果你想使用这个特性,需要确保Java版本支持并且命令行选项正确。如果问题依然存在,那么可能需要调整JVM配置来解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cherami

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值