[Java] GUI编程基础 绘图
库
- swing
- awt
过程
- 创建窗口JFrame
- JFrame-->MenuBar-->Container
- 屏幕坐标系:左上角为原点
- Graphics2D
Main.java
1 import java.awt.EventQueue; 2 import javax.swing.JFrame; 3 4 public class Main { 5 public static void main(String[] args) { 6 EventQueue.invokeLater(()->{ 7 AlgoFrame frame = new AlgoFrame("Welcome",500,500); 8 //AlgoFrame frame = new AlgoFrame("Welcome"); 9 }); 10 } 11 }
AlgoFrame.java
1 import java.awt.Dimension; 2 import java.awt.Graphics; 3 import javax.swing.JFrame; 4 import javax.swing.JPanel; 5 6 public class AlgoFrame extends JFrame{ 7 private int canvasWidth; 8 private int canvasHeight; 9 10 public AlgoFrame(String title, int canvasWidth, int canvasHeight) { 11 super(title); 12 13 this.canvasWidth = canvasWidth; 14 this.canvasHeight = canvasHeight; 15 16 AlgoCanvas canvas = new AlgoCanvas(); 17 setContentPane(canvas); 18 pack(); 19 20 setResizable(false); 21 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 22 setVisible(true); 23 } 24 25 public AlgoFrame(String title) { 26 this(title, 1024, 768); 27 } 28 29 public int getCanvasWidth() {return canvasWidth;} 30 public int getCanvasHeight() {return canvasHeight;} 31 32 private class AlgoCanvas extends JPanel{ 33 @Override 34 public void paintComponent(Graphics g) { 35 super.paintComponent(g); 36 g.drawOval(50, 50, 300, 300); 37 } 38 @Override 39 public Dimension getPreferredSize() { 40 return new Dimension(canvasWidth, canvasHeight); 41 } 42 } 43 }
绘制实心、有颜色的圆形
AlgoFrame.java
1 import java.awt.BasicStroke; 2 import java.awt.Color; 3 import java.awt.Dimension; 4 import java.awt.Graphics; 5 import java.awt.Graphics2D; 6 import java.awt.geom.Ellipse2D; 7 8 import javax.swing.JFrame; 9 import javax.swing.JPanel; 10 11 public class AlgoFrame extends JFrame{ 12 private int canvasWidth; 13 private int canvasHeight; 14 15 public AlgoFrame(String title, int canvasWidth, int canvasHeight) { 16 super(title); 17 18 this.canvasWidth = canvasWidth; 19 this.canvasHeight = canvasHeight; 20 21 AlgoCanvas canvas = new AlgoCanvas(); 22 setContentPane(canvas); 23 pack(); 24 25 setResizable(false); 26 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 27 setVisible(true); 28 } 29 30 public AlgoFrame(String title) { 31 this(title, 1024, 768); 32 } 33 34 public int getCanvasWidth() {return canvasWidth;} 35 public int getCanvasHeight() {return canvasHeight;} 36 37 private class AlgoCanvas extends JPanel{ 38 39 @Override 40 public void paintComponent(Graphics g) { 41 42 super.paintComponent(g); 43 44 Graphics2D g2d = (Graphics2D)g; 45 46 int strokeWidth = 5; 47 g2d.setStroke(new BasicStroke(strokeWidth)); 48 49 g2d.setColor(Color.RED); 50 Ellipse2D circle = new Ellipse2D.Float(50,50,300,300); 51 g2d.draw(circle); 52 53 g2d.setColor(Color.BLUE); 54 Ellipse2D circle2 = new Ellipse2D.Double(50,50,300,300); 55 g2d.fill(circle2); 56 } 57 @Override 58 public Dimension getPreferredSize() { 59 return new Dimension(canvasWidth, canvasHeight); 60 } 61 } 62 }
优化代码
- 将基本操作抽象为函数
- 创建工具类,把“绘制的工具”和“绘制的内容”分开
AlgoVisHelper.java
1 import java.awt.BasicStroke; 2 import java.awt.Color; 3 import java.awt.Graphics2D; 4 import java.awt.geom.Ellipse2D; 5 6 public class AlgoVisHelper { 7 public AlgoVisHelper() {} 8 public static void setStrokeWidth(Graphics2D g2d, int w) { 9 int strokeWidth = w; 10 g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND)); 11 } 12 public static void setColor(Graphics2D g2d, Color color) { 13 g2d.setColor(color); 14 } 15 public static void strokeCircle(Graphics2D g2d, int x, int y, int r) { 16 Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r); 17 g2d.draw(circle); 18 } 19 public static void fillCircle(Graphics2D g2d, int x, int y, int r) { 20 Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r); 21 g2d.fill(circle); 22 } 23 }
抗锯齿(Anti-Aliased)
- 用不同的灰度渲染边缘
- 框架学习的关键:是否知道(勤查文档)
双缓存(Double-Buffered)
- 单缓存的问题:动画中图形位置的刷新导致闪烁(画布清空)
- 如何解决:用两块画布
- JPanel 支持双缓存
AlgoFrame.java
1 import java.awt.Color; 2 import java.awt.Dimension; 3 import java.awt.Graphics; 4 import java.awt.Graphics2D; 5 import java.awt.RenderingHints; 6 7 import javax.swing.JFrame; 8 import javax.swing.JPanel; 9 10 public class AlgoFrame extends JFrame{ 11 private int canvasWidth; 12 private int canvasHeight; 13 14 public AlgoFrame(String title, int canvasWidth, int canvasHeight) { 15 super(title); 16 17 this.canvasWidth = canvasWidth; 18 this.canvasHeight = canvasHeight; 19 20 AlgoCanvas canvas = new AlgoCanvas(); 21 setContentPane(canvas); 22 pack(); 23 24 setResizable(false); 25 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 26 setVisible(true); 27 } 28 29 public AlgoFrame(String title) { 30 this(title, 1024, 768); 31 } 32 33 public int getCanvasWidth() {return canvasWidth;} 34 public int getCanvasHeight() {return canvasHeight;} 35 36 private class AlgoCanvas extends JPanel{ 37 38 public AlgoCanvas() { 39 super(true); 40 } 41 42 @Override 43 public void paintComponent(Graphics g) { 44 45 super.paintComponent(g); 46 47 Graphics2D g2d = (Graphics2D)g; 48 49 //抗锯齿 50 RenderingHints hints = new RenderingHints( 51 RenderingHints.KEY_ANTIALIASING, 52 RenderingHints.VALUE_ANTIALIAS_ON); 53 g2d.addRenderingHints(hints); 54 55 //具体绘制 56 AlgoVisHelper.setStrokeWidth(g2d, 5); 57 58 AlgoVisHelper.setColor(g2d,Color.BLUE); 59 AlgoVisHelper.fillCircle(g2d, canvasWidth/2, canvasHeight/2, 200); 60 61 AlgoVisHelper.setColor(g2d,Color.RED); 62 AlgoVisHelper.strokeCircle(g2d, canvasWidth/2, canvasHeight/2, 200); 63 } 64 @Override 65 public Dimension getPreferredSize() { 66 return new Dimension(canvasWidth, canvasHeight); 67 } 68 } 69 }