1. 位图的磁盘读写:ImageIO
1) AWT允许从磁盘中读取位图并向磁盘中写入位图(必然是按照位图的格式读写了);
2) AWT为位图IO提供的工具就是ImageIO类,只不过IO时使用的都是ImageIO的静态方法,并不需要创建ImageIO的对象之类,就当C语言的函数用就行了,非常方便;
2. ImageIO支持的位图格式:它有4个静态方法可以返回全部支持的位图格式
1) public static String[] getReaderFormatNames(); // 获取可读取的格式
2) public static String[] getReaderFileSuffixes(); // 获取可读取的格式的文件后缀
3) public static String[] getWriterFormatNames(); // 获取可写入的格式
4) public static String[] getWriterFileSuffixes(); // 获取可写入的格式的文件后缀
5) 测试:
String test = ImageIO.xxx();
for (String str: reads) {
System.out.println(str);
}
6) 可以看到支持jpg、jpeg、png、bmp、gif等格式,但是不支持ico格式,因此要避免使用ico格式的位图;
7) 上面方法中的格式名是指正式的格式名称,比如jpeg类型的格式就分别有大写和小写两种写法jpeg和JPEG,但是文件后缀名就统一只有小写的形式,并且返回的字符串中没有后缀点,比如jpeg、png;
3. IO:
1) 真正读写的时候也是使用ImageIO提供的静态方法read和write;
2) 原型:
i. public static BufferedImage ImageIO.read(File input); // 指定从input文件中读取得到一个内存镜像
ii. public static boolean ImageIO.write(RenderedImage im, String formatName, File output);
a. 指定将内存镜像im以格式formatName写入文件output;
b. RenderedImage现在不用理解,就用BufferedImage即可;
c. 格式名就是用getWriterFormatNames的返回值即可;
iii. File类型的构造器就只需要传一个文件名参数即可(String类型);
4. 示例:缩小图片(缩小到80×60)
public class AwtTest {
public void zoom() throws IOException {
BufferedImage srcImg = ImageIO.read(new File("image/board.jpg"));
BufferedImage bufImg = new BufferedImage(80, 60, BufferedImage.TYPE_INT_RGB);
bufImg.getGraphics().drawImage(srcImg, 0, 0, 80, 60, null);
ImageIO.write(bufImg, "jpeg", new File(System.currentTimeMillis() + ".jpg"));
}
public static void main(String[] args) throws IOException {
new AwtTest().zoom();
}
}
!位图放缩的秘诀就是上面重载版本的drawImage方法,其原型:public boolean Graphics.drawImage(Image img, int x, int y, int width, int height, ImageObserver observer);
!!多了width和height参数,它的意思就是把img放缩到width×height的大小画到指定区域中,注意该尺寸不能大于所在容器的尺寸,否则超出部分不予以显示!
5. 五子棋框架程序:
1) 现在可以利用位图IO制作一个图形界面的五子棋程序了,但是我们这里暂不加入判断输赢的逻辑,仅仅就实现落子、展现棋盘等功能;
2) 当然棋盘和棋子包括选中框(当鼠标在棋盘上移动时可以看到在哪个落子位置上都先使用绘图工具绘制好保存在磁盘中;
3) 程序中用到的位图:
!总共4张位图,分别是black.gif、white.gif、seleted.gif、board.gif,分别代表黑子、白子、选中图形和棋盘;
!!它们的尺寸分别是:前三者都是10×12,棋盘是535×536;
!棋盘上棋子数是15×15;
public class AwtTest extends WindowAdapter {
private JFrame f = new JFrame("Gobang");
private ChessBoard board = new ChessBoard();
private final int TABLE_SIZE = 15; // 棋子数是15×15
private final int TABLE_WIDTH = 535; // 棋盘像素尺寸时535×536
private final int TABLE_HEIGHT = 536;
private final int RATE_X = TABLE_WIDTH / TABLE_SIZE; // 每个棋子占像素点多宽和高
private final int RATE_Y = TABLE_HEIGHT / TABLE_SIZE;
private BufferedImage bufTable; // = ImageIO.read(new File("image/board.jpg"));
private final int CHESS_RX = 5; // 棋子横向和纵向的半径宽度,棋盘和棋子并不是严格的正方形
private final int CHESS_RY = 6;
private BufferedImage bufBlack; // = ImageIO.read(new File("image/black.jpg"));
private BufferedImage bufWhite; // = ImageIO.read(new File("image/white.jpg"));
private BufferedImage bufSelected; // = ImageIO.read(new File("image/selected.jpg"));
// 当前鼠标处在棋盘的数组坐标,初始时-1表示鼠标不在棋盘中
private int selectedX = -1;
private int selectedY = -1;
// 分别表示空、有黑子、有白子
private final int NONE = 0;
private final int BLACK = 1;
private final int WHITE = 2;
private int[][] state = new int[TABLE_SIZE][TABLE_SIZE]; // 记录棋盘的状态
// 最终的图形都现在buf镜像中画完再传送
private BufferedImage buf = new BufferedImage(TABLE_WIDTH, TABLE_HEIGHT, BufferedImage.TYPE_INT_RGB);
private Graphics gmm = buf.getGraphics();
class ChessBoard extends JPanel {
@Override
public void paint(Graphics g) {
// 先在内存镜像中画
gmm.drawImage(bufTable, 0, 0, null); // 先画棋盘
if (selectedX >= 0 && selectedY >= 0) { // 再画选中框
gmm.drawImage(bufSelected, selectedX * RATE_X + CHESS_RX, selectedY * RATE_Y + CHESS_RY, null);
}
for (int i = 0; i < TABLE_SIZE; i++) {
for (int j = 0; j < TABLE_SIZE; j++) {
switch (state[i][j]) {
case NONE: break;
case BLACK: gmm.drawImage(bufBlack, i * RATE_X + CHESS_RX, j * RATE_Y + CHESS_RY, null); break;
case WHITE: gmm.drawImage(bufWhite, i * RATE_X + CHESS_RX, j * RATE_Y + CHESS_RY, null); break;
default: break;
}
}
}
g.drawImage(buf, 0, 0, null); // 最后传送
}
}
public void init() throws IOException {
// 清空棋盘
for (int i = 0; i < TABLE_SIZE; i++) {
for (int j = 0; j < TABLE_SIZE; j++) {
state[i][j] = NONE;
}
}
// 读取位图
bufTable = ImageIO.read(new File("image/board.jpg"));
bufBlack = ImageIO.read(new File("image/black.gif"));
bufWhite = ImageIO.read(new File("image/white.gif"));
bufSelected = ImageIO.read(new File("image/selected.gif"));
f.addWindowListener(this);
board.addMouseMotionListener(new MouseMotionAdapter() { // 移动鼠标画选中框
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
// super.mouseMoved(e);
selectedX = (e.getX() - CHESS_RX) / RATE_X;
selectedY = (e.getY() - CHESS_RY) / RATE_Y;
board.repaint();
}
});
board.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) { // 左键落黑子,右键落白子
// TODO Auto-generated method stub
// super.mouseClicked(e);
int x = (e.getX() - CHESS_RX) / RATE_X;
int y = (e.getY() - CHESS_RY) / RATE_Y;
if (state[x][y] == NONE) {
if (e.getButton() == e.BUTTON1) {
state[x][y] = BLACK;
}
else if (e.getButton() == e.BUTTON3) {
state[x][y] = WHITE;
}
board.repaint();
}
}
@Override
public void mouseExited(MouseEvent e) { // 移除棋盘区域就消除选中框
// TODO Auto-generated method stub
// super.mouseExited(e);
selectedX = -1;
selectedY = -1;
board.repaint();
}
});
f.add(board);
board.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
f.pack();
f.setVisible(true);
}
public static void main(String[] args) throws IOException {
new AwtTest().init();
}
}