2.8.3 处理位图
如果仅仅绘制一些简单的几何图形,程序的图形效果依然比较单调 。 AWT 也允许在组件上绘制位图, Graphics 提供了 drawlmage() 方法用于绘制位图,该方法需要一个Image参数一一代表位图,通过该方法就可 以绘制出指定的位图 。
位图使用步骤:
1.创建Image的子类对象BufferedImage(int width,int height,int ImageType),创建时需要指定位图的宽高及类型属性;此时相当于在内存中生成了一张图片;
2.调用BufferedImage对象的getGraphics()方法获取画笔(缓冲区的画笔),此时就可以往内存中的这张图片上绘图了,绘图的方法和之前学习的一模一样;
3.调用组件paint方法中提供的Graphics对象(最终画布上的画笔)的drawImage()方法,一次性的内存中的图片BufferedImage绘制到特定的组件上。
使用位图绘制组件的好处:
使用位图来绘制组件,相当于实现了图的缓冲区,此时绘图时没有直接把图形绘制到组件上,而是先绘制到内存中的BufferedImage上,等全部绘制完毕,再一次性的图像显示到组件上即可,这样用户的体验会好一些。
案例:
通过BufferedImage实现一个简单的手绘程序:通过鼠标可以在窗口中画图。
package Draw;
import javax.swing.plaf.ComboBoxUI;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class HandDraw {
//定义窗口对象
private Frame frame = new Frame("简单手绘程序");
//定义画图区的宽高
private final int AREA_WIDHT = 500;
private final int AREA_HEIGHT = 400;
//定义一个右键菜单,用于设置画笔的颜色
private PopupMenu colorMenu = new PopupMenu();
private MenuItem redItem = new MenuItem("红色");
private MenuItem greenItem = new MenuItem("绿色");
private MenuItem blueItem = new MenuItem("蓝色");
//定义一个变量来记录当前画笔的颜色
private Color forceColor = Color.BLACK;
//创建BufferedImage位图对象,缓冲区
BufferedImage image = new BufferedImage(AREA_WIDHT,AREA_HEIGHT,BufferedImage.TYPE_INT_RGB);
//通过位图,获取关联的Graphics对象,画笔
Graphics g = image.getGraphics();
//自定义一个类来继承Canvas,画布
private class MyCanvas extends Canvas {
@Override
public void paint(Graphics g) {
g.drawImage(image,0,0,null);
}
}
MyCanvas drawArea = new MyCanvas();
//定义变量,来记录鼠标拖动过程中,上一次所处的坐标
private int preX = -1;
private int preY = -1;
public void init() {
//组装视图,逻辑控制
//实现右键菜单更换画笔颜色的逻辑
//先创建事件监听器
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand(); //获取上面的条目
switch (actionCommand) {
case "红色":
forceColor = Color.RED;
break;
case "绿色" :
forceColor = Color.GREEN;
break;
case "蓝色" :
forceColor = Color.BLUE;
break;
}
}
};
//将监听器添加到菜单组件中
redItem.addActionListener(listener);
greenItem.addActionListener(listener);
blueItem.addActionListener(listener);
colorMenu.add(redItem);
colorMenu.add(greenItem);
colorMenu.add(blueItem);
//实现右键出现菜单条的逻辑
//把colorMenu添加给绘图区域
drawArea.add(colorMenu);
//在drawArea中注册鼠标事件监听器
drawArea.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) { //当释放鼠标键时被调用
boolean popupTrigger = e.isPopupTrigger(); //获取点击的是鼠标的哪个键
if(popupTrigger) { //true则说明是右键
colorMenu.show(drawArea,e.getX(),e.getY());
}
else {
//倘若不是右键,则说明监听到拖动结束的标志了
//重置preX和preY
preX = -1;
preY = -1;
}
}
});
//实现绘图的逻辑
//先设置位图的背景为白色
g.setColor(Color.WHITE);
g.fillRect(0,0,AREA_WIDHT,AREA_HEIGHT);
//通过监听鼠标的移动,完成线条绘制
drawArea.addMouseMotionListener(new MouseMotionAdapter() {
//该方法,当鼠标左键按下,并进行拖动时,会被调用
@Override
public void mouseDragged(MouseEvent e) {
//注意这里是画在缓冲区
//判断一下是否第一次拖动
if(preX>0 && preY>0) {
//画线条,需要两组坐标,分别是线条的起点和终点, e.getX()和 e.getY()可以获取鼠标坐标
//这里是终点的坐标,因此需要先记录起点的坐标
g.setColor(forceColor);
g.drawLine(preX, preY, e.getX(), e.getY());
}
//修正preX和preY的值
preX = e.getX();
preY = e.getY();
//重绘组件,到画布中
drawArea.repaint();
}
});
drawArea.setPreferredSize(new Dimension(AREA_WIDHT,AREA_HEIGHT));
frame.add(drawArea);
//设置窗口最佳大小和可见性
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new HandDraw().init();
}
}