Java 图形绘制与动画制作全解析
1. Java 图形绘制基础
在 Java 中,我们可以利用多边形和其他形状来绘制图形。虽然加载像 .GIF 和 .JPG 这样的图像文件似乎更简单,但使用多边形绘制图形有两个显著优势:
-
速度快
:即使是小图标,加载和显示图像文件也比绘制一系列多边形要慢。
-
可缩放性好
:通过改变创建多边形的参数,能轻松改变整个图像的大小,且比图像文件缩放更快、效果更好。
以下是一个绘制特定形状的代码示例:
// finish sign
comp2D.setColor(Color.red);
GeneralPath sign3 = new GeneralPath();
sign3.moveTo(110F, 78F);
sign3.lineTo(321F, 289F);
sign3.lineTo(290F, 317F);
sign3.lineTo(81F, 107F);
sign3.closePath();
comp2D.fill(sign3);
编译并在命令行运行该程序后,输出应类似于特定的图形。
2. 绘制饼图
接下来,我们将创建一个名为
PiePanel
的图形用户界面组件来显示饼图。
PiePanel
是
JPanel
的子类,使用它的程序需按以下步骤操作:
1. 使用构造方法
PiePanel(int)
创建
PiePanel
对象,参数指定饼图的切片数量。
2. 调用对象的
addSlice(Color, float)
方法为每个切片指定颜色和值。
例如,以下是使用
PiePanel
表示美国学生贷款还款数据的代码:
PiePanel loans = new PiePanel(4);
loans.addSlice(Color.green, 101F);
loans.addSlice(Color.yellow, 68F);
loans.addSlice(Color.blue, 91F);
loans.addSlice(Color.red, 25F);
| 贷款状态 | 金额(十亿美元) |
|---|---|
| 学生已偿还金额 | 101 |
| 在校学生贷款金额 | 68 |
| 还款中学生贷款金额 | 91 |
| 违约学生贷款金额 | 25 |
为了实现
PiePanel
,我们还需要一个辅助类
PieSlice
来表示每个切片:
class PieSlice {
Color color = Color.lightGray;
float size = 0;
PieSlice(Color pColor, float pSize) {
color = pColor;
size = pSize;
}
}
PiePanel
类的完整代码如下:
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
public class PiePanel extends JPanel {
private PieSlice[] slice;
private int current = 0;
private float totalSize = 0;
private Color background;
public PiePanel(int sliceCount) {
slice = new PieSlice[sliceCount];
background = getBackground();
}
public void addSlice(Color sColor, float sSize) {
if (current <= slice.length) {
slice[current] = new PieSlice(sColor, sSize);
totalSize += sSize;
current++;
}
}
public void paintComponent(Graphics comp) {
super.paintComponent(comp);
Graphics2D comp2D = (Graphics2D) comp;
int width = getSize().width - 10;
int height = getSize().height - 15;
int xInset = 5;
int yInset = 5;
if (width < 5)
xInset = width;
if (height < 5)
yInset = height;
comp2D.setColor(background);
comp2D.fillRect(0, 0, getSize().width, getSize().height);
comp2D.setColor(Color.lightGray);
Ellipse2D.Float pie = new Ellipse2D.Float(
xInset, yInset, width, height);
comp2D.fill(pie);
float start = 0;
for (int i = 0; i < slice.length; i++) {
float extent = slice[i].size * 360F / totalSize;
comp2D.setColor(slice[i].color);
Arc2D.Float drawSlice = new Arc2D.Float(
xInset, yInset, width, height, start, extent,
Arc2D.Float.PIE);
start += extent;
comp2D.fill(drawSlice);
}
}
}
为了测试
PiePanel
,我们创建一个使用它的小程序
PieApplet
:
import java.awt.*;
import javax.swing.*;
public class PieApplet extends JApplet {
Color uneasyBeingGreen = new Color(0xCC, 0xCC, 0x99);
Color zuzusPetals = new Color(0xCC, 0x66, 0xFF);
Color zootSuit = new Color(0x66, 0x66, 0x99);
Color sweetHomeAvocado = new Color(0x66, 0x99, 0x66);
Color shrinkingViolet = new Color(0x66, 0x66, 0x99);
Color miamiNice = new Color(0x33, 0xFF, 0xFF);
Color inBetweenGreen = new Color(0x00, 0x99, 0x66);
Color norwegianBlue = new Color(0x33, 0xCC, 0xCC);
Color purpleRain = new Color(0x66, 0x33, 0x99);
Color freckle = new Color (0x99, 0x66, 0x33);
public void init() {
Container pane = getContentPane();
PiePanel pie = new PiePanel(10);
pie.addSlice(uneasyBeingGreen, 1284);
pie.addSlice(zuzusPetals, 1046);
pie.addSlice(zootSuit, 281);
pie.addSlice(sweetHomeAvocado, 232);
pie.addSlice(shrinkingViolet, 176);
pie.addSlice(miamiNice, 148);
pie.addSlice(inBetweenGreen, 143);
pie.addSlice(norwegianBlue, 133);
pie.addSlice(purpleRain,130);
pie.addSlice(freckle, 127);
pane.add(pie);
setContentPane(pane);
}
}
同时,创建一个简单的网页
PieApplet.html
来包含这个小程序:
<applet code="PieApplet.class" width="300" height="200">
</applet>
这个小程序展示了 10 个国家的人口数据饼图。当调整小程序窗口大小时,饼图会根据新尺寸重新绘制,因为其 (x,y)、高度和宽度变量基于
PiePanel
的大小。
3. 常见问题解答
-
如何绘制顺时针的弧线?
可以通过将弧线大小指定为负数来实现。例如:
Arc2D.Float smile = new Arc2D.Float(35F, 20F, 15F, 20F,
0F, -90F, Arc2D.Float.OPEN);
-
Ellipses.Float构造方法中指定的 (x,y) 坐标是什么?
这些坐标代表椭圆或圆的最小 x 值和最小 y 值,相当于围绕它们绘制的无形矩形的左上角坐标。
4. 小测验
-
在程序中绘制图形前,使用什么方法更改当前颜色?
- a. shiftColor()
- b. setColor()
-
c. Could you repeat the question?
答案:b。可以使用setBackground()方法设置小程序的背景颜色,使用Graphics类的setColor()方法选择当前颜色。
-
如果想使用组件的高度和宽度来确定绘制图形的大小,可以使用什么?
- a. A ruler and a friend who’s good at math
- b. getHeight() and getWidth()
-
c. getSize().height and getSize().width
答案:c。
-
第一个示例程序关注的社会问题是什么?
- a. Overpopulation
- b. Defaulted student loans
-
c. People who compress air in places with signs that clearly indicate it is prohibited, especially restaurants
答案:c。不过人口过剩也是个大问题。
5. 活动建议
-
创建一个
PieApplet类的版本,将颜色值和饼图切片值作为参数,而不是硬编码在小程序的源代码中。 -
创建一个
Sign类的版本,使其形状能根据面板的可用空间进行调整,就像PiePanel组件那样。
6. Java 动画制作
在 Java 中,我们还可以实现动画效果。动画的基本原理是在特定位置绘制图像,移动图像位置,然后让计算机在新位置重新绘制图像。
以下是一个使用一系列图像文件创建动画的示例程序
Animate.java
:
import java.awt.*;
public class Animate extends javax.swing.JApplet
implements Runnable {
Image[] picture = new Image[6];
int totalPictures = 0;
int current = 0;
Thread runner;
int pause = 500;
public void init() {
for (int i = 0; i < 6; i++) {
String imageText = null;
imageText = getParameter("image"+i);
if (imageText != null) {
totalPictures++;
picture[i] = getImage(getCodeBase(), imageText);
} else
break;
}
String pauseText = null;
pauseText = getParameter("pause");
if (pauseText != null) {
pause = Integer.parseInt(pauseText);
}
}
public void paint(Graphics screen) {
super.paint(screen);
Graphics2D screen2D = (Graphics2D) screen;
if (picture[current] != null)
screen2D.drawImage(picture[current], 0, 0, this);
}
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
public void run() {
Thread thisThread = Thread.currentThread();
while (runner == thisThread) {
repaint();
current++;
if (current >= totalPictures)
current = 0;
try {
Thread.sleep(pause);
} catch (InterruptedException e) { }
}
}
public void stop() {
if (runner != null) {
runner = null;
}
}
}
这个程序使用线程来处理动画,通过
Thread.sleep()
方法控制每个图像的显示时间。动画的图像通过网页参数获取,参数名从
image0
开始,最多可显示 6 个图像。动画速度由
pause
参数指定。
7. 加载和显示图像
在 Java 中,使用
getImage()
方法加载图像,该方法需要两个参数:包含图像文件的 Web 地址或文件夹,以及图像文件名。例如:
Image turtlePicture = getImage(getCodeBase(), "Mertle.gif");
在
paint()
方法中,使用
drawImage()
方法显示图像。为了避免动画闪烁,该程序的
paint()
方法不调用其父类的
paint()
方法。
8. 总结
通过本文,我们学习了 Java 中图形绘制和动画制作的基础知识。图形绘制方面,使用多边形绘制图形具有速度快和可缩放性好的优势;动画制作方面,利用线程和图像加载方法可以实现简单的动画效果。希望这些知识能帮助你在 Java 编程中创造出更丰富的多媒体应用。
Java 图形绘制与动画制作全解析
9. 动画实现原理深入剖析
动画的实现依赖于线程的运用,这是因为动画通常是一个持续的过程,需要在程序响应用户输入的同时,独立地控制图像的显示和切换。在
Animate
程序中,线程的使用尤为关键,它使得动画的各个环节能够有条不紊地进行。以下是对
Animate
程序中线程相关部分的详细剖析:
import java.awt.*;
public class Animate extends javax.swing.JApplet
implements Runnable {
Image[] picture = new Image[6];
int totalPictures = 0;
int current = 0;
Thread runner;
int pause = 500;
public void init() {
for (int i = 0; i < 6; i++) {
String imageText = null;
imageText = getParameter("image"+i);
if (imageText != null) {
totalPictures++;
picture[i] = getImage(getCodeBase(), imageText);
} else
break;
}
String pauseText = null;
pauseText = getParameter("pause");
if (pauseText != null) {
pause = Integer.parseInt(pauseText);
}
}
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
public void run() {
Thread thisThread = Thread.currentThread();
while (runner == thisThread) {
repaint();
current++;
if (current >= totalPictures)
current = 0;
try {
Thread.sleep(pause);
} catch (InterruptedException e) { }
}
}
public void stop() {
if (runner != null) {
runner = null;
}
}
}
-
init()方法 :该方法负责初始化动画所需的图像和暂停时间。通过循环遍历参数,获取图像文件名并加载图像,同时根据pause参数设置动画的暂停时间。 -
start()方法 :当runner线程为空时,创建一个新的线程并启动它。这确保了动画在小程序启动时开始运行。 -
run()方法 :这是动画的核心部分,使用while循环不断执行以下操作:-
调用
repaint()方法,请求重绘屏幕,以显示新的图像。 -
递增
current变量,指向下一个要显示的图像。 -
如果
current超过了总图像数,将其重置为 0,实现循环显示。 -
使用
Thread.sleep(pause)方法暂停一段时间,控制动画的速度。
-
调用
-
stop()方法 :当小程序停止时,将runner线程置为null,停止动画的运行。
10. 动画优化策略
为了提升动画的性能和视觉效果,我们可以采取以下优化策略:
-
减少闪烁
:如前文所述,为避免动画闪烁,
Animate程序的paint()方法不调用其父类的paint()方法。此外,还可以使用双缓冲技术,先在内存中绘制整个图像,然后一次性将其显示在屏幕上,减少屏幕刷新的次数。 -
动态调整图像数量
:可以修改
Animate程序,使其能够根据实际情况动态调整可显示的图像数量,而不是固定为 6 个。这样可以增加程序的灵活性。 -
优化线程管理
:在动画停止时,确保线程资源被正确释放,避免内存泄漏。可以在
stop()方法中添加更多的清理代码,确保线程安全退出。
11. 图形绘制与动画的综合应用案例
以下是一个综合应用图形绘制和动画的案例,展示了如何在一个程序中同时实现静态图形绘制和动态动画效果。
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
public class CombinedApplet extends JApplet implements Runnable {
// 图形绘制相关变量
private PiePanel pie;
// 动画相关变量
Image[] pictures = new Image[3];
int totalPics = 0;
int currentPic = 0;
Thread animator;
int delay = 300;
public void init() {
// 初始化图形绘制
Container pane = getContentPane();
pie = new PiePanel(3);
pie.addSlice(Color.red, 100);
pie.addSlice(Color.green, 200);
pie.addSlice(Color.blue, 150);
pane.add(pie);
// 初始化动画
for (int i = 0; i < 3; i++) {
String imgText = getParameter("img" + i);
if (imgText != null) {
totalPics++;
pictures[i] = getImage(getCodeBase(), imgText);
}
}
String delayText = getParameter("delay");
if (delayText != null) {
delay = Integer.parseInt(delayText);
}
}
public void start() {
if (animator == null) {
animator = new Thread(this);
animator.start();
}
}
public void run() {
Thread thisThread = Thread.currentThread();
while (animator == thisThread) {
repaint();
currentPic++;
if (currentPic >= totalPics) {
currentPic = 0;
}
try {
Thread.sleep(delay);
} catch (InterruptedException e) { }
}
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
if (pictures[currentPic] != null) {
g2d.drawImage(pictures[currentPic], 200, 200, this);
}
}
public void stop() {
if (animator != null) {
animator = null;
}
}
}
这个程序在一个小程序中同时实现了饼图的绘制和动画效果。在
init()
方法中,初始化了饼图和动画所需的图像;在
run()
方法中,实现了动画的循环显示;在
paint()
方法中,绘制当前的动画图像。
12. 流程图展示
下面是
Animate
程序的执行流程图:
graph TD;
A[小程序启动] --> B[init()方法];
B --> C{是否有图像参数};
C -- 是 --> D[加载图像];
C -- 否 --> E[结束加载];
D --> F{是否有pause参数};
F -- 是 --> G[设置暂停时间];
F -- 否 --> H[使用默认暂停时间];
B --> I[start()方法];
I --> J[启动线程];
J --> K[run()方法];
K --> L[调用repaint()];
L --> M[显示图像];
M --> N[递增current];
N --> O{current是否超过总图像数};
O -- 是 --> P[重置current为0];
O -- 否 --> Q[继续];
P --> Q;
Q --> R[Thread.sleep()];
R --> L;
A --> S[stop()方法];
S --> T[停止线程];
13. 总结与展望
通过本文的学习,我们全面了解了 Java 中图形绘制和动画制作的相关知识。从使用多边形绘制图形到创建复杂的动画效果,我们掌握了多种技术和方法。图形绘制方面,多边形的使用为我们提供了快速、可缩放的图形解决方案;动画制作方面,线程的运用使得我们能够实现流畅的动画效果。
在未来的开发中,我们可以进一步拓展这些知识,结合更多的 Java 特性,如事件处理、网络编程等,创造出更加丰富和交互性强的多媒体应用。例如,开发一个基于网络的动画游戏,让用户能够实时参与和互动;或者创建一个动态的图形报表系统,根据实时数据更新图形显示。希望大家能够不断探索和实践,将这些知识运用到实际项目中,创造出更优秀的 Java 程序。
Java图形绘制与动画制作全解析
超级会员免费看
1261

被折叠的 条评论
为什么被折叠?



