(Graphics2D) g;
Java 2D 库采用面向对象的方式将几何图形组织起来。包含描述直线、 矩形的椭圆的类:
Line2D
Rectangle2D
Ellipse2D
这些类全部实现了 Shape 接口。
注释:Java 2D 库支持更加复杂的图形, 例如圆弧、二次曲线、三次曲线和通用路径。有关更详细的内容请参看卷 2 第 7 章。
要想绘制图形,首先要创建一个实现了 Shape 接口的类的对象, 然后调用 GraphicS2D 类 中的 draw 方法。例如,
Rectangle2D rect = . . .;
g2.draw(rect);
注释: 在 Java 2D 库出现之前, 程序员使用 Grpahics 类中的 drawRectangle 方法绘制图形。从表面上看, 老式风格的方法调用起来好像更加简单一点。然而,使用 Java 2D 库, 可以选择 Java 2D 库中提供的一些工具提高绘制能力。
使用 Java 2D 图形类或许会增加一些复杂度。在 1.0 的绘制方法中, 采用的是整型像素坐标, 而 Java 2D 图形采用的是浮点坐标。在很多情况下,用户可以使用更有意义的形式 (例如,微米或英寸)指定图形的坐标,然后再将其转换成像素,这样做很方便。在 Java 2D 库中, 内部的很多浮点计算都采用单精度 float。毕竟, 几何计算的最终目的是要设置屏幕或 打印机的像素, 所以单精度完全可以满足要求了。只要舍入误差限制在一个像素的范围内, 视觉效果就不会受到任何影响。
然而,有时候程序员处理 float 并不太方便, 这是因为 Java 程序设计语言在将 double 值 转换成 float 值时必须进行类型转换。例如,考虑下列的语句:
float f = 1.2; // Error
这条语句无法通过编译,因为常量 1.2 属于 double 类型,而编译器不允许丢失精度。解 决的方法是给浮点常量添加一个后缀 F:
float f = 1.2F; // Ok
现在,看一下这条语句:
Rectang1e2D r = . . .
float f = r.getWidth(); // Error
这条语句也无法通过编译, 其原因与前面一样。由于 getWidth 方法的返回类型是 double, 所以需要进行类型强制转换:
float f = (float) r.getWidth(): // OK
由于后缀和类型转换都有点麻烦, 所以 2D 库的设计者决定为每个图形类提供两个版本: 一个是为那些节省空间的程序员提供的 float 类型的坐标;另一个是为那些懒惰的程序员提供 的 double 类型的坐标(本书主要采用的是第二个版本, 即 double 类型的坐标)。
这个库的设计者选择了一种古怪且在最初看起来还有些混乱的方式进行了打包。看一下 Rectangle2D 类, 这是一个拥有两个具体子类的抽象类,这两个具体子类也是静态内部类:
Rectangle2D.Float
Rectang1e2D.Double
图 10-9显示了它们之间的继承示意图。
最好淡化这两个具体类是静态内部类, 这样做只是为了避免使用 FloatRectangle2D 和 DoubleRectangle2D 这样的名字(有关静态内部类更详细的信息请参看第 6 章)。
当 创 建 一 个 Rectangle2D.Float 对 象 时, 应 该 提 供 float 型 数 值 的 坐 标。 而 创 建 Rectangle2D. Double 对象时,应该提供 double 型数值的坐标。
Rectangle2D.FIoat floatRect = new Rectangle2D.Float(10.OF, 25.OF, 22.SF, 20.OF);
Rectangle2D.Double doubleRect = new Rectangle2D.Double(10.0, 25.0, 22.5, 20.0);
实 际 上, 由 于 Rectangle2D.Float 和 Rectangle2D.Double 都 扩 展 于 Rectangle2D 类, 并 且子类只覆盖了 RectangldD 超类中的方法, 所以没有必要记住图形类型。可以直接使用 Rectangle2D 变量保存矩形的引用。
Rectangle2D floatRect = new Rectangle2D.FIoat(10.OF, 25.OF, 22.5F , 20.OF);
Rectangle2D doubleRect = new Rectangle2D.Double(10.0, 25.0, 22.5, 20.0);
也就是说, 只有在构造图形对象时,才需要使用烦人的内部类。
构造参数表示矩形的左上角位置、宽和髙。
注释: 实际上, Rectangle2D.Float 类包含了一个不是由 Rectangle2D 继承而来的附加方法 setRect(float x, float y, float h, float w) 。如果将 Rectangle2D.Float 的引用存储在 Rectangle2D 变量中, 那就会失去这个方法。但是,这也没有太大关系, 因为在 Rectangle2D 中有一个 参教为 double 类型的 setRect 方法。
Rectangle2D方法的参数和返回值均为 double 类型。例如, 即使 Rectangle2D.Float 对象 存储 float 类型的宽度,getWidth 方法也返回一个 double 值。
提示:直接使用 Double 图形类可以避免处理 float 类型的值, 然而如果需要创建上千个 图形对象, 还是应该考虑使用 Float 类,这样可以节省存储空间。
前面对 Rectangle2D 类的论述也适用于其他图形类。另外,Point2D 类也有两个子类Point2D.Float 和 Point2D.Double。下面是构造一个点对象的方法:
Point2D p = new Point2D.Double (10 , 20);
提示:Point2D 类是很有用的。使用 Point2D 对象比使用单独的 x 和 y 更加具有面向对象的风格。许多构造器和方法都接收 Point2D 型参数, 我们建议在可能的情况下使用 Point2D 对象。这样会使几何计算更容易理解。
Rectangle2D 和 Ellipse2D 类都是由公共超类 RectangularShape 继承来的。无可非议, 楠 圆不是矩形, 但它们都有着矩形边界, 如图 10-10 所示。
RectangularShape 类定义了 20 多个有关图形操作的通用方法, 其中比较常用的方法有 getWidth、getHeight、 getCenterX、getCenterY 等(但在写本书时,getCenter 方法 还不能以 Point2D 对象的形式返回中心位置)。
最后, 从 Java 1.0 遗留下来的两个类也被放置在图形类的继承层次中。它们是 Rectangle 和 Point 类, 分别扩展于 Rectangle2D 和 Point2D 类,并用整型坐标存储矩形和点。
图 10-11 给出了图形类之间的关系。 不过, 省略了Double 和 Float 子类。图中的遗留类采用填充灰色的方式标记。
Rectangle2D 和 Ellipse2D 对象很容易构造。需要给出
• 左上角的 x 和 y 坐标;
• 宽和高。
对于椭圆,这些内容代表外接矩形。例如,
E11ipse2D e = new Ellipse2D.Double(150, 200, 100, 50);
用左上角位于(150, 200) 、宽 100、高 50 的外接矩形构造一个椭圆。
然而,有时候并不知道左上角的位置。经常得到的是矩形的两个对角点, 而这两个对角不一定是左上角和右下角。不能直接这样构造一个矩形:
Rectangle2D rect = new Rectangle2D.0ouble(px, py, qx - px, qy - py); // Error
如果 p 不是左上角,两个坐标之差就为负,矩形就为空。在这种情况下,首先创建一个 空矩形,然后调用 setFrameFromDiagonal 方法,如下所示:
Rectangle2D rect = new Rectangle2D.Doub1e();
rect.setFrameFromDiagonal (px, py, qx, qy);
或者,如果已知的顶点分别用 Point2D 类型的两个对象 p 和 q 表示,就应该这样调用:
rect.setFrameFroeiiiDiagonal (p, q);
在构造楠圆(这种情况还出现在构造其他图形时)时,通常可以知道椭圆的中心、宽和 高,而不是外接矩形的顶点。setFrameFromCenter 方法使用中心点,但仍然要给出四个顶点中的一个。因此,通常采用下列方式构造橢圆:
E11ipse2D ellipse = new E111pse2D.Doub1e(centerX - width / 2, centerY - height / 2, width, height);
要想构造一条直线,需要提供起点和终点。这两个点既可以使用 Point2D 对象表示,也可以使用一对数值表示:
Line2D line = new Line2D.Double(start, end);
Line2D line = new Line2D.0ouble(startX, startY, endX, endY);
程序清单 10-4 中的程序绘制了一个矩形;这个矩形的内接椭圆;矩形的对角线以及以矩形中心为圆点的圆。图 10-12 显示了结果。(略过)
API java.awt.geom.RectangularShape 1.2
• double getCenterX( )
• double getCenterY( )
• double getMinX( )
• double getMinY( )
• double getMaxX( )
• double getMaxY( )
返回闭合矩形的中心, 以及最小、 最大 x 和 y 坐标值。
• double getWidth( )
• double getHeight( )
返回闭合矩形的宽和高。
• double getX( )
• double getY( )
返回闭合矩形左上角的 x 和 y 坐标。
API java.awt.geom.Rectangular2D.Double 1.2
• Rectangle2D . Double(double x ,double y , double w , double h )
利用给定的左上角、宽和高, 构造一个矩形。
API java.awt.geom.Rectangular2D.Float 1.2
• Rectangle2D . FIoat(f1oat x ,float y,float w ,float h )
利用给定的左上角、 宽和高, 构造一个矩形。
API java.awt.geom.Ellipse2D.Double 1.2
• Ellipse2D . Double( double x , double y ,double w , double h )
利用给定的左上角、 宽和高的外接矩形, 构造一个椭圆。
API java.awt.geom.Point2D.Double 1.2
• Point2D . Double(double x , double y )
利用给定坐标构造一个点。
API java.awt.geom.Line2D.Double 1.2
• Line2D .Double(Point2D start , Point2D end )
• Line2D . Double(double startX , double startY, double endX , double endY )
使用给定的起点和终点, 构造一条直线。
10.6 使用颜色
使用 Graphics2D 类的 setPaint 方法可以为图形环境上的所有后续的绘制操作选择颜色。 例如:
g2.setPaint(Color.RED);
g2.drawString("Warning!", 100, 100);
只需要将调用 draw 替换为调用 fill 就可以用一种颜色填充一个封闭图形(例如: 矩形或 椭圆)的内部:
Rectangle2D rect = . . .;
g2 .setPaint(Color.RED);
g2 .fill(rect); // fills rect with red
要想绘制多种颜色, 就需要按照选择颜色、 绘制图形、 再选择另外一种颜色、 再绘制图形的过程实施。
注释: fill 方法会在右侧和下方少绘制一个像素。 例如, 如果绘制一个 new Rectangle2D. Double(0, 0, 10, 20), 绘制的矩形将包括 x = 10 和 y = 20 的像素。如果填充这个矩形, 则不会绘制 x = 10 和 y = 20 的像素。
Color 类用于定义颜色。在 java.awt.Color 类中提供了 13 个预定义的常量, 它们分別表 示 13 种标准颜色。
BLACK , BLUE, CYAN, DARK.GRAY, CRAY, GREEN, LIGHT_CRAY , MACENTA, ORANGE, PINK, RED, WHITE, YELLOW
注释: 在 Java SE 1.4 之前的版本中, 颜色常量的名字为小写形式, 例如, Color.red。 这似乎有些超出寻常, 因为标准编码的惯例是采用大写形式书写常量。现在可以采用大写的形式书写标准颜色的名字,不过,为了向后兼容, 也可以用小写形式书写。
可以通过提供红、 绿和蓝三色成分来创建一个 Color 对象, 以达到定制颜色的目的。三 种颜色都是用 0 ~ 255(也就是一个字节)之间的整型数值表示, 调用 Color 的构造器格式为:
Color(int redness, int greenness, int blueness)
下面是一个定制颜色的例子:
g2.setPaint(new Color(0, 128, 128)); // a dull blue-green
g2.drawString("Welcome!", 75, 125);
注释: 除了纯色以外,还可以选择更复杂的“ 颜料” 设置,例如, 改变色调( hue) 或者图像。有关这方面更加详细的内容请参看卷 2 中的高级 AWT 章节。如果使用 Graphics 对象, 而不是 Graphics2D 对象, 就需要使用 setColor 方法设置颜色。
要想设置背景颜色, 就需要使用 Component 类中的 setBackground 方法。Component 类 是 JComponent 类的祖先。
MyComponent p = new HyComponent():
p.setBackground(Color.PINK);
另外,还有一个 setForeground方法,它是用来设定在组件上进行绘制时使用的默认颜色。
提示:从名字就可以看出,Color 类中的 brighter( ) 方法和 darker( ) 方法的功能, 它们分别加亮或变暗当前的颜色。使用 brighter 方法也是加亮条目的好办法。实际上, brighter() 只微微地加亮一点。要达到耀眼的效果, 需要调用三次这个方法:c.brighter( ). brighter( ). brighter( )。
Java 在 SystemColor 类中预定义了很多颜色的名字。在这个类中的常量, 封装了用户系统的各个元素的颜色。例如,
p.setBackground(SystemColor.window)
它将把面板的背景颜色设定为用户桌面上所有窗口使用的默认颜色。(无论何时重新绘制窗口, 都会填充背景颜色。)当希望让绘制的用户界面元素与用户桌面上已经存在的其他元素的颜色匹配时, 使用 SystemColor 类中的颜色非常有用。表 10-1 列出了系统颜色的名字和它们的含义。
• Paint getPaint( )
• void setPaint( Paint p )
获取或设置这个图形环境的绘制属性。Color 类实现了 Paint 接口。因此, 可以使用这个方法将绘制属性设置为纯色。
• void fill ( Shape s)
用当前的颜料填充该图形。
API java.awt.Componet 1.0
• Color getBackground( )
• void set Background(Color c )
获取或设置背景颜色。
参数:c 新背景颜色
• Color getForeground( )
• void setForeground(Color c )
获取或设置前景颜色。
参数:c 新前景颜色
10.7 文本使用特殊字体
在本章开始的“ Not a Hello, World” 程序中用默认字体显示了一个字符串。实际上,经常希望选用不同的字体显示文本。人们可以通过字体名( font face name) 指定一种字体。字体名由“ Helvetica” 这样的字体家族名(font family name) 和一个可选的“ Bold” 后缀组成。 例如,“ Helvetica” 和“ HelveticaBold” 属于“ Helvetica ” 家族的字体。
要想知道某台特定计算机上允许使用的字体, 就需要调用 GraphicsEnvironment 类中的 getAvailableFontFamilyNames 方法。这个方法将返回一个字符型数组, 其中包含了所有可用 的字体名。GraphicsEnvironment 类描述了用户系统的图形环境, 为了得到这个类的对象,需要 调用静态的 getLocalGraphicsEnvironment 方法。下面这个程序将打印出系统上的所有字体名:
import java.awt.*;
public class ListFonts
public static void main(String[] args)
String[] fontNames = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
for (String fontName : fontNames)
System.out.println(fontName);
在某个系统上,输出的结果为:
Abadi MT Condensed Light
Arial
Arial Black
Arial Narrow
Arioso
Baskerville
Binner Gothic
后面还有 70 种左右的字体。
字体名可以商标化, 字体设计在一些权限内可以版权化。因此,字体的分发需要向字体的创始者付版税。当然,像名牌香水有廉价仿制品一样, 字体也有外观相似的。例如, Helvetica 的仿制品就是 Windows 中称为 Arial 的字体。 为了创建一个公共基准, AWT 定义了五个逻辑(logical) 字体名:
SansSerif
Serif
Monospaced
Dialog
Dialoglnput
这些字体将被映射到客户机上的实际字体。例如,在 Windows 系统中, SansSerif将被映 射到 Arial。
另外,Oracle JDK 包含 3 种字体,它们是“ Lucida Sans”,“ Lucida Bright” 和“ Lucida Sans Typewriter" 。
要想使用某种字体绘制字符, 必须首先利用指定的字体名、字体风格和字体大小来创建 —个 Font 类对象。下面是构造一个 Font 对象的例子:
Font sansboldl4 = new Font(°SansSerif", Font.BOLD, 14);
第三个参数是以点数目计算的字体大小。点数目是排版中普遍使用的表示字体大小的单位,每英寸包含 72 个点。
在 Font 构造器中,提供字体名的位置也可以给出逻辑字体名称。另外, 利用 Font 构造器的 第二个参数可以指定字体的风格(常规、加粗、斜体或加粗斜体,) 下面是几个字体凤格的值:
Font.PLAIN
Font.BOLD
Font.ITALIC
Font.BOLD + Font.ITALIC
注释: 字体映射定义在 Java 安装的 jre/lib 子目录中的 fontconfig.properties 文件中。 有 关 这 个 文 件 的 详 细 内 容 请 参 看 http://docs.oracle.eom/javase/8/docs/tedmotes/guides/intl/ fontconfig.html o
可以读取 TrueType 或 PostScriot Type 1 格式的字体文件。这需要一个字体输入流 通常从磁盘文件或者 URL 读取(有关流的更详细信息请参看卷 2 第 1 章。) 然后调用静态方法 Font.createFont:
URL url = new URL("http://www.fonts.com/Wingbats.ttf");
InputStream in = url.openStream();
Font fl = Font.createFont(Font.TRUETYPE_FONT, in);
上面定义的字体为常规字体,大小为 1 。 可以使用 deriveFont 方法得到希望大小的字体:
Font f = fl.deriveFont(14.0F);
警告: deriveFont 方法有两个重载版本。一个(有一个 float 参数)设置字体的大小;另一 个(有一个 int 参数)设置字体风格。所以 f.deriveFont(14) 设置的是字体风格, 而不是大小(其结果为斜体, 因为 14 的二进制表示的是 ITALIC, 而 不 是 BOLD)。
Java 字体 包 含 了 通 用 的 ASCII 字 符 和 符 号。 例 如, 如 果 用 Dialog 字 体 打 印 字 符 ‘ \u2297’,那么就会看到 × 字符。只有在 Unicode 字符集中定义的符号才能够使用。
下面这段代码将使用系统中丨4 号加粗的标准 sans serif字体显示字符串“ Hello,World”:
Font sansbo1dl4 = new Font("SansSerif", Font.BOLD, 14);
g2.setFont(sansbo1dl4);
String message = "Hello, World!";
g2.drawString(message, 75, 100);
接下来, 将字符串绘制在面板的中央,而不是任意位置。因此, 需要知道字符串占据的 宽和高的像素数量。这两个值取决于下面三个因素:
• 使用的字体(在前面列举的例子中为 sans serif,加粗,14 号;
• 字符串(在前面列举的例子中为“ Hello,World”;)
• 绘制字体的设备(在前面列举的例子中为用户屏幕)。
要想得到屏幕设备字体属性的描述对象, 需要调用 GraphicS2D 类中的 getFontRenderContext 方法。它将返回一个 FontRenderContext 类对象。可以直接将这个对象传递给 Font 类 的 getStringBounds 方法:
FontRenderContext context = g2.getFontRenderContext();
Rectangle2D bounds = sansboldl4..getStringBounds(message, context);
getStringBounds 方法将返回包围字符串的矩形。
为了解释这个矩形的大小, 需要清楚几个排版的相关术语。如图 10-13 所示。基线 (baseline) 是一条虚构的线, 例如,字母“ e” 所在的底线。上坡度(ascent) 是从基线到坡顶 ( ascenter) 的距离。例如,“ b” 和“ k” 以及大写字母的上面部分。下坡度(descent) 是从基 线到坡底(descenter) 的距离, 坡底是“ p” 和“ g” 这种字母的底线。
行间距( leading) 是某一行的坡底与其下一行的坡顶之间的空隙(这个术语源于排字机分隔行的间隔带。) 字体的高度是连续两个基线之间的距离, 它等于下坡度 + 行间距 + 上坡度。
getStringBounds 方法返回的矩形宽度是字符串水平方向的宽度。矩形的高度是上坡度、 下坡度、 行间距的总和。这个矩形始于字符串的基线,矩形顶部的 y 坐标为负值。因此,可 以采用下面的方法获得字符串的宽度、 髙度和上坡度:
double stringWidth = bounds.getWidth();
double stringHeight = bounds.getHeight();
double ascent = -bounds.getY();
如果需要知道下坡度或行间距,可以使用 Font 类的 getLineMetrics 方法。这个方法将返 回一个 LineMetrics 类对象,获得下坡度和行间距的方法是:
LineMetrics metrics = f.getLineMetrics(message, context);
float descent = raetrics.getDescent();
float leading = metrics.getLeading();
下面这段代码使用了所有这些信息, 将字符串显示在包围它的组件中央:
FontRenderContext context = g2.getFontRenderContext();
Rectang1e2D bounds = f.getStringBounds(message, context);
// (x,y) = top left comer of text
double x = (getWidth() - bounds.getWidth()) / 2;
double y = (getHeight() - bounds.getHeight()) / 2;
// add ascent to y to reach the baseline
double ascent = -bounds.getY();
double baseY = y + ascent;
g2.drawString(message, (int) x, (int) baseY);
为了能够获得中央的位置, 可以使用 getWidth() 得到组件的宽度。 使用 bounds. getWidth( ) 得到字符串的宽度。前者减去后者就是两侧应该剩余的空间。 因此, 每侧剩余的空间应该是这个差值的一半。高度也是一样。
注释: 如果需要在 paintComponent 方法外部计算布局图 的尺度, 不能从 Graphics2D 对象得到字体绘制环境。换 作调用 JComponent 类的 getFontMetrics 方法, 而后紧接 着调用 getFontRenderContext:
FontRenderContext context = getFontMetncs(f) .getFontRenderContext ();
为了说明位置是正确的, 示例程序绘制了基线和包围这个字符串的矩形。 程序清单 10-5 中是相应的代码。(略过)
API java.awt.Font 1.0
• Font(String name, int style, int size)
创建一个新字体对象。
参数: name 字体名。 不是字体名(例如,“ Helvetica Bold”), 就是逻辑字体名 ( 例如,“ Serif”、“ SansSerif”)
style 字体风格(Font.PLAIN、 Font.BOLD、 Font.ITALIC 或 Font.BOLD+Font. ITALIC)
size 字体大小(例如, 12 )
• String getFontName( ) 返回字体名, 例如,“ Helvetica Bold”。
• String getFamily( ) 返回字体家族名,例如,“ Helvetica”。
• String getName( ) 如果采用逻辑字体名创建字体, 将返回逻辑字体, 例如,“ SansSerif”;否则, 返回字 体名。
• Rectangle2D getStringBounds(String s , FontRenderContext context) 1.2
返回包围这个字符串的矩形。矩形的起点为基线。矩形顶端的 y 坐标等于上坡度的负 值。矩形的高度等于上坡度、下坡度和行间距之和。宽度等于字符串的宽度。
• LineMetrics getLineMetrics(String s , FontRenderContext context) 1.2
返回测定字符串宽度的一个线性 metrics 对象。 • Font deriveFont(int style) 1.2
• Font deriveFont(f1oat size) 1.2
• Font deriveFont(int style, float size) 1.2
返回一个新字体, 除给定大小和字体风格外, 其余与原字体一样。
API java.awt.font.LineMetncs 1.2
• float getAscent( ) 返回字体的上坡度—从基线到大写字母顶端的距离。
• float getDescent( ) 返回字体的下坡度—从基线到坡底的距离。
• float getLeading( ) 返回字体的行间距—从一行文本底端到下一行文本顶端之间的空隙。
• float getHeight( ) 返回字体的总高度—两条文本基线之间的距离(下坡度 + 行间距 + 上坡度)。
API java.awt.Graphics 1.0
• Font getFont( )
• void setFont(Font font)
获取或设置当前的字体。这种字体将被应用于后续的文本绘制操作中。
参数:font —种字体
• void drawString(String str, int x, int y)
采用当前字体和颜色绘制一个字符串。
参数:str 将要绘制的字符串
x 字符串开始的 x 坐标
y 字符串基线的 y 坐标
API java.awt.Graphics2D 1.2
• FontRenderContext getFontRenderContext()
返回这个图形文本中, 指定字体特征的字体绘制环境。
• void drawString(String str, float x, float y)
采用当前的字体和颜色绘制一个字符串。
参数: str 将要绘制的字符串
x 字符串开始的 x 坐标
y 字符串基线的 y 坐标
API javax.swing.JComponent 1.2
• FontMetrics getFontMetrics(Font f) 5.0 获取给定字体的度量。FontMetrics 类是 LineMetrics 类的早先版。
API java.awt.FontMetrics 1.0
• FontRenderContext getFontRenderContext() 1.2 返回字体的字体绘制环境。
10.8 显示图像
到目前为止,我们已经看到了如何通过绘制直线和图形创建一个简单的图像。而对于照 片这样的复杂图像来说,通常都是由扫描仪或特殊的图像处理软件生成的(正像在卷2中将 看到的,逐像素地生成图像。
一旦图像保存在本地文件或因特网的某个位置上,就可以将它们读到 Java 应用程序中, 并在 Graphics 对象上进行显示。读取图像有很多方法。在这里我们使用你之前已经见过的 Imagelcon 类:
Image image = new Imagelcon(filename).getlmage();
这里的变量 image 包含了一个封装图像数据的对象引用。可以使用 Graphics类的 drawlmage 方法将图像显示出来。
public void paintComponent(Graphics g)
g.drawlmage(image, x, y, null);
程序清单 10-6 又前进了一步, 它在一个窗口中平铺显 示了一幅图像。 屏幕显示的结果如图 10-15 所示。这里采用 paintComponent 方法来实现平铺显示。它的基本过程为: 先在左上角显示图像的一个拷贝, 然后使用 copyArea 将其 拷贝到整个窗口:
for (int i = 0; i * imageWidth <= getWidth() ; i++)
for (int j = 0; j * imageHeight <= getHeight(); j++)
if (i + j > 0)
g.copyArea(0, 0, imageWidth, imageHeight, i * imageWidth, j * imageHeight);
程序清单 10-6 列出了图像显示程序的完整代码。
API java.awt.Graphics 1.0
• boolean drawlmage( Image img, int x , int y, ImageObserver observer )
绘制一幅非比例图像。
注意: 这个调用可能会在图像还没有绘制完毕就返回。
参数: img 将要绘制的图像
x 左上角的 x 坐标
y 左上角的 y 坐标
observer 绘制进程中以通告为目的的对象(可能为 null)。
• boolean drawlmage(Image img, int x,int y,int width,int height , ImageObserver observer )
绘制一幅比例图像。系统按照比例将图像放人给定宽和高的区域。注意:这个调用可能会在图像还没有绘制完毕就返回。
参数: img 将要绘制的图像
x 左上角的x坐标
y 左上角的 y 坐标
width 描述图像的宽度
height 描述图像的髙度
observer 绘制进程中以通告为目的的对象(可能为 null)
• void copyArea(int x,int y,int width,int height,int dx,int dy)
拷贝屏幕的一块区域。
x 原始区域左上角的 x 坐标
y 原始区域左上角的 y 坐标
width 原始区域的宽度
height 原始区域的高度
dx 原始区域到目标区域的水平距离
dy 原始区域到目标区域的垂直距离
以上完成了有关 Java 图形编程的内容介绍。关于更高级的技术,可以参看卷 II 中有关 2D 图形和图像管理的讨论。在下一章,读者将学习如何让程序对用户的输人进行响应。