仓库:Java图形化界面: Java图形化界面学习demo与资料 (gitee.com)
如果仅仅绘制一些简单的几何图形,程序的图形效果依然比较单调 。 AWT 也允许在组件上绘制位图, Graphics 提供了 drawlmage() 方法用于绘制位图,该方法需要一个Image参数一一代表位图,通过该方法就可 以绘制出指定的位图 。
位图使用步骤:
1.创建Image的子类对象BufferedImage(int width,int height,int ImageType),创建时需要指定位图的宽高及类型属性;此时相当于在内存中生成了一张图片;
2.调用BufferedImage对象的getGraphics()方法获取画笔,此时就可以往内存中的这张图片上绘图了,绘图的方法和之前学习的一模一样;
3.调用组件的drawImage()方法,一次性的内存中的图片BufferedImage绘制到特定的组件上。
使用位图绘制组件的好处:
使用位图来绘制组件,相当于实现了图的缓冲区,此时绘图时没有直接把图形绘制到组件上,而是先绘制到内存中的BufferedImage上,等全部绘制完毕,再一次性的图像显示到组件上即可,这样用户的体验会好一些。
案例:
通过BufferedImage实现一个简单的手绘程序:通过鼠标可以在窗口中画图。

演示代码:
- package awt_swimg.day04;
-
- import awt_swimg.day01.Utils;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.image.BufferedImage;
-
- public class HandDraw {
-
- //定义画图区的宽高
- private final int AREA_WIDTH = 500;
- private final int AREA_HEIGHT = 400;
-
- //定义变量,保存上一次鼠标拖动时,鼠标的坐标
- private int preX = -1;
- private int preY = -1;
- //定义一个右键菜单,用于设置画笔的颜色
- private PopupMenu popupMenu=new PopupMenu();
- private MenuItem redItem = new MenuItem("红色");
- private MenuItem greenItem = new MenuItem("绿色");
- private MenuItem buleItem = new MenuItem("蓝色");
- //定义一个BufferedImage对象
- private BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB);
- //获取BufferedImage对象关联的画笔
- private Graphics g=image.getGraphics();
- //定义窗口对象
- private JFrame frame = new JFrame("简单手绘程序");
- //定义画布对象
- private Canvas canvas=new Canvas(){
- @Override
- public void paint(Graphics g) {
- g.drawImage(image,0,0,null);
- }
- };
- //定义一个Color对象,用来保存用户设置的画笔颜色,默认为黑色
- private Color color = Color.BLACK;
- public void init(){
-
- redItem.addActionListener(e -> color = Color.red);
- greenItem.addActionListener(e -> color = Color.GREEN);
- buleItem.addActionListener(e -> color = Color.BLUE);
- canvas.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseReleased(MouseEvent e) {
- if (e.isPopupTrigger()) {
- popupMenu.show(canvas, e.getX(), e.getY());
- }
- preX = -1;
- preY = -1;
- }
- });
- canvas.addMouseMotionListener(new MouseMotionAdapter() {
- @Override
- public void mouseDragged(MouseEvent e) {
- if (preX > 0 && preY > 0) {
- g.setColor(color);
- g.drawLine(preX, preY, e.getX(), e.getY());
- }
- preX = e.getX();
- preY = e.getY();
- canvas.repaint();
- }
- });
- g.fillRect(0,0,AREA_WIDTH,AREA_HEIGHT);
- canvas.setPreferredSize(new Dimension(AREA_WIDTH,AREA_HEIGHT));
- canvas.add(popupMenu);
- popupMenu.add(redItem);
- popupMenu.add(greenItem);
- popupMenu.add(buleItem);
-
- frame.add(canvas);
- Utils.setJFrame(frame);
- }
-
- public static void main(String[] args) {
- new HandDraw().init();
- }
-
-
-
- }
在实际生活中,很多软件都支持打开本地磁盘已经存在的图片,然后进行编辑,编辑完毕后,再重新保存到本地磁盘。如果使用AWT要完成这样的功能,那么需要使用到ImageIO这个类,可以操作本地磁盘的图片文件。
| 方法名称 | 方法功能 |
| static BufferedImage read(File input) | 读取本地磁盘图片文件 |
| static BufferedImage read(InputStream input) | 读取本地磁盘图片文件 |
| static boolean write(RenderedImage im, String formatName, File output) | 往本地磁盘中输出图片文件 |
案例:
编写图片查看程序,支持另存操作
演示代码:
- import javax.imageio.ImageIO;
- import java.awt.image.BufferedImage;
- import java.io.File;
-
- public class ReadAndSaveImage {
-
- private Frame frame = new Frame("图片查看器");
-
- private BufferedImage image;
-
- private class MyCanvas extends Canvas{
-
- @Override
- public void paint(Graphics g) {
- if (image!=null){
- g.drawImage(image,0,0,image.getWidth(),image.getHeight(),null);
- }
- }
- }
-
- private MyCanvas imageComponent = new MyCanvas();
-
- public void init() throws Exception{
-
- //设置菜单项
- MenuBar mb = new MenuBar();
- Menu menu = new Menu("文件");
- MenuItem openItem = new MenuItem("打开");
- MenuItem saveItem = new MenuItem("另存为");
-
- openItem.addActionListener(e -> {
- //弹出对话框,选择本地图片
- FileDialog oDialog = new FileDialog(frame);
- oDialog.setVisible(true);
- //读取用户选择的图片
- String dir = oDialog.getDirectory();
- String file = oDialog.getFile();
- try {
- image = ImageIO.read(new File(dir,file));
-
- imageComponent.repaint();
-
- } catch (IOException e1) {
- e1.printStackTrace();
- }
-
- });
-
-
- saveItem.addActionListener(e -> {
- //弹出对话框,另存为
- FileDialog sDialog = new FileDialog(frame,"保存图片",FileDialog.SAVE);
- sDialog.setVisible(true);
- String dir = sDialog.getDirectory();
- String file = sDialog.getFile();
-
- try {
- ImageIO.write(image,"JPEG",new File(dir,file));
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- });
-
- mb.add(menu);
- menu.add(openItem);
- menu.add(saveItem);
-
- frame.setMenuBar(mb);
- frame.add(imageComponent);
-
- frame.setBounds(200,200,800,600);
-
- frame.setVisible(true);
-
- frame.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- System.exit(0);
- }
- });
- }
-
-
-
- public static void main(String[] args) throws Exception {
- new ReadAndSaveImage().init();
- }
- }
接下来,我们使用之前学习的绘图技术,做一个五子棋的游戏。
演示代码:
- package awt_swimg.day04;
-
- import awt_swimg.day01.Utils;
-
- import javax.imageio.ImageIO;
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
-
- public class Gobang {
- //定义三个BufferedImage,分别代表棋盘图、黑子图、白子图
- private BufferedImage table;
- private BufferedImage black;
- private BufferedImage white;
-
- //定义一个BufferedImage,代表当鼠标移动时将要下子的选择框
- private BufferedImage selected;
-
- //定义棋盘的宽高,这里的定义尺寸和给定的board.jpg图片的尺寸一致因为棋盘背景是通过图片加载的
- private final int TABLE_WIDTH = 535;
- private final int TABLE_HEIGHT = 536;
-
- //定义棋盘中,每行和每列可下子的数目,这个数目跟给定的board.jpg中的数目是一致的,都为15
- private final int BOARD_SIZE = 15;
-
- //定义每个棋子所占棋盘总宽度的大小比率;每个棋子所占宽度 535/15=35
- private final int RATE = TABLE_WIDTH / BOARD_SIZE;
-
- //定义棋盘有效区域与背景图坐标之间的偏移值,x坐标右移5个像素,y坐标下移6个像素
- private final int X_OFFSET = 5;
- private final int Y_OFFSET = 6;
- /*
- 定义一个二维数组充当棋盘上每个位置处的棋子;
- 该数组的索引与该棋子在棋盘上的坐标需要有一个对应关系:
- 例如: 索引[2][3]处的棋子,对一个的真实绘制坐标应该是:
- xpos = 2*RATE+X_OFFSET=75;
- ypos = 3*RATE+Y_OFFSET=111;
- */
- private int[][] board = new int[BOARD_SIZE][BOARD_SIZE];//如果存储0,代表没有棋子,如果存储1,代表黑棋,如果存储2,代表白棋
-
- //定义五子棋游戏窗口
- private JFrame frame = new JFrame("五子棋游戏");
-
- //定义变量,记录当前选中的坐标点对应的boad数组中对应的棋子索引;
- private int selectX = -1;
- private int selectY = -1;
-
- //定义一个变量,记录当前用户选择下的是白棋还是黑棋还是清除,清除:0,黑棋:1,白棋:2;
- private int chessCategory = 1;
-
- private JPanel canvas = new JPanel() {
- @Override
- public void paint(Graphics g) {
- g.drawImage(table, 0, 0, null);
- if (selectX > 0 && selectY > 0) {
- g.drawImage(selected, selectX * RATE + X_OFFSET, selectY * RATE + Y_OFFSET, null);
- }
- for (int i = 0; i < BOARD_SIZE; i++) {
- for (int j = 0; j < BOARD_SIZE; j++) {
- if (board[i][j] == 2) {
- g.drawImage(white, i * RATE + X_OFFSET, j * RATE + Y_OFFSET, null);
- }
- if (board[i][j] == 1) {
- g.drawImage(black, i * RATE + X_OFFSET, j * RATE + Y_OFFSET, null);
- }
- }
- }
- }
- };
- private Panel panel = new Panel();
- private Button whiteChess = new Button("白棋");
- private Button blackChess = new Button("黑棋");
- private Button delete = new Button("删除");
-
-
- public void init() throws IOException {
- //初始化数组,默认
- for (int i = 0; i < BOARD_SIZE; i++) {
- for (int j = 0; j < BOARD_SIZE; j++) {
- board[i][j] = 0;
- }
- }
- canvas.addMouseMotionListener(new MouseMotionAdapter() {
- @Override
- public void mouseMoved(MouseEvent e) {
- selectX = (e.getX() - X_OFFSET) / RATE;
- selectY = (e.getY() - Y_OFFSET) / RATE;
- canvas.repaint();
- }
-
- });
- canvas.addMouseListener(new MouseAdapter() {
-
- @Override
- public void mouseClicked(MouseEvent e) {
- int xChess = (e.getX() - X_OFFSET) / RATE;
- int yChess = (e.getY() - Y_OFFSET) / RATE;
- board[xChess][yChess] = chessCategory;
- canvas.repaint();
- }
-
- @Override
- public void mouseExited(MouseEvent e) {
- selectX = -1;
- selectY = -1;
- canvas.repaint();
- }
- });
- whiteChess.addActionListener(e -> {
- chessCategory = 2;
- this.setButtonColor(Color.green,Color.white,Color.white);
- });
- blackChess.addActionListener(e -> {
- chessCategory = 1;
- this.setButtonColor(Color.white,Color.green,Color.white);
- });
- delete.addActionListener(e -> {
- chessCategory = 0;
- this.setButtonColor(Color.white,Color.white,Color.green);
- });
-
-
- table = ImageIO.read(new File("src/awt_swimg/img/board.jpg"));
- white = ImageIO.read(new File("src/awt_swimg/img/white.gif"));
- black = ImageIO.read(new File("src/awt_swimg/img/black.gif"));
- selected = ImageIO.read(new File("src/awt_swimg/img/selected.gif"));
- canvas.setPreferredSize(new Dimension(table.getWidth(), table.getHeight()));
-
-
- panel.add(whiteChess);
- panel.add(blackChess);
- panel.add(delete);
- frame.add(canvas);
- frame.add(panel, BorderLayout.SOUTH);
- Utils.setJFrame(frame);
-
-
- }
-
- public void setButtonColor(Color w,Color b ,Color d){
- whiteChess.setBackground(w);
- blackChess.setBackground(b);
- delete.setBackground(d);
- }
-
- public static void main(String[] args) throws IOException {
- new Gobang().init();
- }
- }