这部分是我阅读 《Head first Java》 的GUI部分笔记
个人认为GUI其实没有必要再学了
这部分学完,可以结合多线程等设计实现坦克大战,飞机大战等游戏了
绘图
java坐标系
左上角为坐标原点,以像素为单位.在java坐标系中,第一个是x坐标,表示当前位置的水平方向,距离坐标原点x个像素;第二个坐标是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素
原点为窗口的左上角,如果参数设置为负,图形可能无法完全显示出来
像素是一个密度单位,不是长度单位,两者无法比较
使用到的类
JFrame可以理解为一个窗口,一个画框/画板
JPanel可以理解为一支画板/画纸
Graphics g ,把 g 理解成一支画笔
总之,展示图形的类要继承JFrame
基本步骤:
- 需要先有一张画纸(继承JPanel),在画板上画图形
- 有了画板就要有一支画笔,就要重写JPanel的paint方法(调用父类构造器完成初始化)
- 让要展示图形的类继承JFrame,JFrame相当于一个画板/画框(画纸放在它上边)
- 在展示图形的类中先定义一张画纸,之后初始化这张画纸
- 初始化好画纸后将画纸放到会画板上,用从JFrame哪里继承来的add方法
- 设置窗口大小
- 最后在main中创建一个画图对象实例
绘图原理
- paint(Graphics g)绘制组件的外观
- repaint()刷新组件的外观
何时调用paint()
- 当组件第一次显示在屏幕上时会调用paint()
- 窗口最大化或最小化时调用paint()
- 拖动窗口,使得窗口大小发生变化时调用paint()
- repaint()方法会被调用
简单演示
先画一个圆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
import com.sun.javafx.logging.JFRInputEvent;
import javax.swing.*; import java.awt.*;
public class DrawCircle extends JFrame { private MyPanel mp =null;
public static void main(String[] args) { new DrawCircle(); } public DrawCircle() { mp = new MyPanel(); this.add(mp); this.setSize(800,500); this.setVisible(true); } }
class MyPanel extends JPanel { @Override public void paint(Graphics g) { super.paint(g);
g.drawOval(15,15,200,200); } }
|
画其他图形
解释都在注释中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| import javax.swing.*; import java.awt.*; import java.util.Scanner;
@SuppressWarnings({"all"}) public class DrawOther extends JFrame { private MyPanel2 mp2 = null;
public static void main(String[] args) { input(); }
public static void input() { DrawOther drawOther = new DrawOther(); System.out.println("+---选择要画的图形---+"); System.out.println(" 1.直线"); System.out.println(" 2.矩形"); System.out.println(" 3.填充矩形"); System.out.println(" 4.填充椭圆"); System.out.println(" 5.画图片"); System.out.println(" 6.画字符串"); System.out.println(" 0.退出"); System.out.println("+------------------+"); Scanner scanner = new Scanner(System.in); int choice = scanner.nextInt(); drawOther.Draw_(choice); }
public void Draw_(int choice) { switch (choice) { case 1: mp2 = new MyPanel2(); this.add(mp2); break; case 2: MyPanel3 mp3 = new MyPanel3(); this.add(mp3); break; case 3: MyPanel4 mp4 = new MyPanel4(); this.add(mp4); break; case 4: MyPanel5 mp5 = new MyPanel5(); this.add(mp5); break; case 5: MyPanel6 mp6 = new MyPanel6(); this.add(mp6); break; case 6: MyPanel7 mp7 = new MyPanel7(); this.add(mp7); break; default: System.out.println("输入错误"); return; } this.setSize(800, 500); this.setVisible(true); } }
class MyPanel2 extends JPanel { @Override public void paint(Graphics g) { super.paint(g); g.drawLine(25, 25, 90, 85); g.drawLine(90, 85, 40, 92); g.drawLine(40, 92, 25, 25); } }
class MyPanel3 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics); graphics.drawRect(10, 10, 100, 100); graphics.drawRect(45, 45, 145, 155); } }
class MyPanel4 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics); graphics.setColor(Color.blue); graphics.fillRect(10, 10, 100, 100); graphics.setColor(Color.yellow); graphics.fillRect(50, 50, 130, 150); } }
class MyPanel5 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics); graphics.setColor(Color.black); graphics.fillOval(25, 25, 100, 160); } }
class MyPanel6 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics); Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/wb.png")); graphics.drawImage(image,10,10,221,234,this); } }
class MyPanel7 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics); graphics.setColor(Color.black); graphics.setFont(new Font("行楷", Font.BOLD ,50)); graphics.drawString("冯雯",100,100); graphics.setFont(new Font("隶书",Font.BOLD,50)); graphics.drawString("张永锐",100,200); } }
|
关于颜色
得到随机颜色的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class RandomColor_ { public static void main(String[] args) { JFrame frame = new JFrame(); MyPanel1 mp1 = new MyPanel1(); frame.add(mp1); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800,800); frame.setVisible(true); } } class MyPanel1 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics);
int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red,green,blue); graphics.setColor(randomColor); graphics.fillOval(70,70,100,100);
red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); randomColor = new Color(red,green,blue); graphics.setColor(randomColor); graphics.fillOval(70,180,100,100);
red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); randomColor = new Color(red,green,blue); graphics.setColor(randomColor); graphics.fillOval(170,125,100,100); } }
|
渐变颜色
Gradient(意思是梯度,渐变)
使用类GradientPaint,表示渐变画嘛
1 2 3 4
| Graphics2D g2d = (Graphics2D) graphics; GradientPaint gradient = new GradientPaint(170,125,Color.blue,270,225,Color.orange); g2d.setPaint(gradient); graphics.fillOval(170,125,100,100);
|
与随机颜色结合(可执行程序)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class RandomColor_ { public static void main(String[] args) { JFrame frame = new JFrame(); MyPanel1 mp1 = new MyPanel1(); frame.add(mp1); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800,800); frame.setVisible(true); } } class MyPanel1 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics);
int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red,green,blue); graphics.setColor(randomColor); graphics.fillOval(70,70,100,100);
red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); randomColor = new Color(red,green,blue); graphics.setColor(randomColor); graphics.fillOval(70,180,100,100);
Graphics2D g2d = (Graphics2D) graphics; GradientPaint gradient = new GradientPaint(170,125,randomColor,270,225,Color.orange); g2d.setPaint(gradient); graphics.fillOval(170,125,100,100); } }
|
得到一个按钮
使用按钮类JButton,注意,这里不是继承JFrame了,JFrame可以直接被使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class GUI_first { public static void main(String[] args) {
JFrame frame = new JFrame(); JButton button = new JButton("我是一个按钮,点击我");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.setSize(300,300);
frame.setVisible(true); } }
|
取得对象的事件
设置好了按钮就要对应按钮来执行事件,按钮按下后整么反应
接下来看文件取得用户的事件
不要再放在中间
frame.getContentPane().add(button);//把button加到
向上面直接使用add不给它更多的参数,会直接将画好的图形放在中间位置
其实add是可以有参数的
使用一个类BorderLayout(意思是边境布局(就表示布局嘛))
可选择的布局
根据英文其实已经能够看的懂了,也不多,合理选择即可
如下程序规定了图形放置添加位置:
规定位置的代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class GUI_third { public static void main(String[] args) { JFrame frame = new JFrame(); MyPanel2 myPanel2 = new MyPanel2(); JButton jButton = new JButton("Button1"); JButton button2 = new JButton("Button2"); JButton button3 = new JButton("Button3"); JButton button4 = new JButton("Button4"); frame.getContentPane().add(BorderLayout.CENTER,myPanel2); frame.getContentPane().add(BorderLayout.AFTER_LAST_LINE,jButton); frame.getContentPane().add(BorderLayout.AFTER_LINE_ENDS,button2); frame.getContentPane().add(BorderLayout.BEFORE_LINE_BEGINS,button3); frame.getContentPane().add(BorderLayout.NORTH,button4); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(500,500); frame.setVisible(true); } } class MyPanel2 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics); graphics.fillOval(0,0,100,100); } }
|
规定位置的代码演示的图形展示
注意,面板是在中间,只是圆形不在面板的中间而已,不是说面板不在中间
事件
接下来结合事件处理,做到点一下按钮将圆形的填充颜色换一下取得用户的事件
使用java.awt.event包中的事件对象,如:MouseEvent、KeyEvent、WindowEvent、ActionEvent等
每个事件类型都要有个接听窗口,例如想要接收MouseEvent就要实现MouseListener这个接口
取得按钮的ActionEvent
- 实现ActionEvent这个接口
- 像按钮注册(告诉按钮要监听的事件)
- 定义事件处理的方法(实现接口的方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import javax.swing.*; import java.awt.event.*;
public class SimpleGui1B implements ActionListener { JButton button;
public static void main(String[] args) { SimpleGui1B gui = new SimpleGui1B(); gui.go(); }
public void go(){ JFrame frame = new JFrame(); button = new JButton("click me");
button.addActionListener(this);
frame.getContentPane().add(button); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300,300);定义窗口大小 frame.setVisible(true); }
public void actionPerformed(ActionEvent event){ button.setText("I've been clicked"); } }
|
结合事件处理转换填充颜色
编写一个程序,有按钮和一个面板,面板随机产生不同颜色的填充圆,通过点击按钮可以切换圆的颜色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
public class GUI_fourth implements ActionListener { JFrame frame; public static void main(String[] args) { new GUI_fourth().go(); } public void go(){ frame = new JFrame(); JButton button1 = new JButton("Change Color"); button1.addActionListener(this);
MyPanel3 myPanel3 = new MyPanel3(); frame.getContentPane().add(BorderLayout.CENTER,myPanel3); frame.getContentPane().add(BorderLayout.SOUTH,button1);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(500,500); frame.setVisible(true); } public void actionPerformed(ActionEvent event){ frame.repaint(); } } class MyPanel3 extends JPanel { @Override public void paint(Graphics graphics) { super.paint(graphics);
int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); Color color1 = new Color(red,green,blue);
red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); Color color2 = new Color(red,green,blue);
Graphics2D g2d = (Graphics2D) graphics;
GradientPaint gradientPaint = new GradientPaint(190, 180, color1, 300, 300, color2); g2d.setPaint(gradientPaint);
g2d.fillOval(190,180,100,100); } }
|
实现两个按钮分别处理事件
通过内部类实现最好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
public class GUI_fifth { JFrame frame; JLabel label;
public static void main(String[] args) { new GUI_fifth().go(); }
public void go(){ frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton label_button = new JButton("Change Label"); label_button.addActionListener(new LabelListener());
JButton color_button = new JButton("Change Color"); color_button.addActionListener(new ColorListener());
label = new JLabel("I'm a label"); MyPanel4 myPanel4 = new MyPanel4();
frame.getContentPane().add(BorderLayout.WEST,label); frame.getContentPane().add(BorderLayout.CENTER,myPanel4); frame.getContentPane().add(BorderLayout.SOUTH,color_button); frame.getContentPane().add(BorderLayout.EAST,label_button);
frame.setSize(500,500); frame.setVisible(true); } class LabelListener implements ActionListener { @Override public void actionPerformed(ActionEvent event) { label.setText("Changed"); } } class ColorListener implements ActionListener { @Override public void actionPerformed(ActionEvent event){ frame.repaint(); } } } @SuppressWarnings({"all"}) class MyPanel4 extends JPanel { @Override public void paint(Graphics g){ g.setColor(Color.cyan); g.fill3DRect(0,0,500,500,false); int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); Color stare_color = new Color(red, green, blue); red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); Color end_color = new Color(red, green, blue);
Graphics2D g2d = (Graphics2D) g;
GradientPaint gradient = new GradientPaint(110,180,stare_color,210,180,end_color); g2d.setPaint(gradient);
g2d.fillOval(110,180,100,100); } }
|
让图形动起来
通过点击按钮使得图形按固定方向移动
通过改变x和y(起始坐标)来每次重新画图,但是要注意抹去原本的痕迹
改变了x和y的值之后再直接调用继承了JPanel的类的方法:repaint()
下面的程序不仅实现了运动,还实现了事件处理(点一下按钮,动一下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
public class GUI_sixth { int x = 70; int y = 70; MyDrawPanel drawPanel = new MyDrawPanel();
public static void main(String[] args) { new GUI_sixth().go(); }
public void go() { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Make the Circle Move"); button.addActionListener(new Color_Button());
frame.getContentPane().add(BorderLayout.CENTER,drawPanel); frame.getContentPane().add(BorderLayout.SOUTH,button);
frame.setSize(500,500); frame.setVisible(true); }
class Color_Button implements ActionListener { @Override public void actionPerformed(ActionEvent actionEvent) { for(int i = 0;i<3;i++) { x++; y++;
drawPanel.repaint();
try { Thread.sleep(25); } catch (Exception ex) { } } } }
class MyDrawPanel extends JPanel { public void paintComponent(Graphics g){ g.setColor(Color.white); g.fill3DRect(0,0,this.getWidth(),this.getHeight(),true);
int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); Color stare_color = new Color(red, green, blue); red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); Color end_color = new Color(red, green, blue);
Graphics2D g2d = (Graphics2D) g;
GradientPaint gradient = new GradientPaint(110,180,stare_color,210,180,end_color); g2d.setPaint(gradient);
g2d.fillOval(x,y,50,50); } } }
|
通过键盘控制移动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener;
public class GUI_seventh { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); MyPanel myPanel = new MyPanel(); frame.getContentPane().add(BorderLayout.CENTER,myPanel); frame.addKeyListener(myPanel); frame.setSize(500,500); frame.setVisible(true); } }
class MyPanel extends JPanel implements KeyListener { int x = 10; int y = 10;
@Override public void paint(Graphics graphics) { super.paint(graphics); int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); Color startColor = new Color(red, green, blue); red = (int) (Math.random() * 255); green = (int) (Math.random() * 255); blue = (int) (Math.random() * 255); Color endColor = new Color(red, green, blue); Graphics2D g2d = (Graphics2D) graphics; GradientPaint gradient = new GradientPaint(0,0,startColor,500,500,endColor); g2d.setPaint(gradient); graphics.fillOval(x, y, 50, 50); }
@Override public void keyTyped(KeyEvent keyEvent) {
}
@Override public void keyPressed(KeyEvent keyEvent) { if (keyEvent.getKeyCode() == KeyEvent.VK_UP) { y-=3; this.repaint(); } else if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) { y+=3; this.repaint(); } else if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) { x+=3; this.repaint(); } else if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) { x-=3; this.repaint(); } }
@Override public void keyReleased(KeyEvent keyEvent) {
} }
|