Java改进:验证码,流星雨,swing,线程,键盘事件,点击事件,图片移动【诗书画唱】
题目:每间隔0.1秒就依次打印出”一起来看流星雨“中的一个字
以下是改进版的代码,有个人的超级详细易懂的理解内容和注释内容!

package swing;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.Random;
import javax.swing.*;
public class starNew {
public static void main(String[] args) {
huaTu huaTu=new huaTu();
Thread Thread=new Thread(huaTu);
Thread.start();
}
}
//个人的理解:
//huaTu extends JFrame:这里必须用huaTu来继承JFrame,而不是用
//starNew来继承JFrame,因为要让文字依次地被打印出来,
//那么就是每次打印一个字的时候,JFrame就要用repaint()同时刷新一次。
//用starNew来继承JFrame时,就是会等写的sleep方法和repaint()刷新,执行完后,
//文字都被打印出来后,才会有新的JFrame自动
//“this.setVisible(true)”和主函数中new starNew()出来。
class huaTu extends JFrame implements Runnable{
public huaTu(){
//5个基本属性:
this.setLayout(null);
this.setSize(600,600);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public void paint(Graphics g){
Random r=new Random();
//设置画笔的颜色为黑色:
g.setColor(Color.black);
//画个矩形(整个的黑色背景):
g.fillRect(0,0,600,600);
//绘制图片人物:
Image img=Toolkit.getDefaultToolkit().getImage("人.png");
g.drawImage(img,100,250,100,250,this);
//绘制星星:
g.setColor(Color.white);
for(int i=0;i<100;i++){
g.drawString("*",r.nextInt(600),r.nextInt(200));
}
//绘制一个月亮:
g.fillOval(400,50,80,80);
g.setColor(Color.black);
g.fillOval(389,50,80,80);
//一起去看流星雨思路:将文字转为字符数组,用for循环每打印一个文字,
//就文字休眠0.1秒。
char[] charArray="一起去看流星雨".toCharArray();
g.setColor(Color.white);
g.setFont(new Font("微软雅黑",Font.BOLD,30));
for(int i=0;i<charArray.length;i++){
g.drawString(charArray[i]+"",450,200+(i*30));
try {
Thread.sleep(100);
//这里的休眠同时控制文字和星星的每改变一次的时间间隔为0.1秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
repaint();
// 这里的重绘repaint()方法是为了刷新
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}



每点击一次后就让用paint方法等画的矩形的x轴和y轴方向的位移发生改变,就是让矩形动

package swing;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class jvXing extends JFrame{
public static JButton anNiu=null;
public static void main(String[] args) {
new jvXing();
}
public jvXing(){
this.setLayout(null);
this.setSize(500,500);
this.setLocationRelativeTo(null);
huaTuClass huaTuClass=new huaTuClass();
huaTuClass.setBounds(0,0,400,400);
anNiu=new JButton("刷新");
anNiu.setBounds(410, 100, 70, 30);
anNiu.addActionListener(huaTuClass);
this.add(anNiu);
this.add(huaTuClass);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
//graphics 英[ˈɡræfɪks]
//美[ˈɡræfɪks]
//n. 图样; 图案; 绘图; 图像;
//
//huaTuClass:画图类,继承面板类,用Graphics和paint等,来画图
class huaTuClass extends JPanel implements ActionListener{
int x,y=0;//设置初始的x轴或y轴的距离的变量为0
public void paint(Graphics g){
//用clearRect方法刷新页面的时候清空页面上的所有内容
// rect
// [词典] 矩形(Rectangular); 矩形结构; 矩形区域;
g.clearRect(0, 0, this.getWidth(), this.getHeight());
// 个人总结的语法:
// this.getWidth()和this.getHeight()表示整个面板的宽和高
// g.clearRect(要清空区域的X轴方向位移,
// 要清空区域的y轴方向位移,
// 要清空区域的宽, 要清空区域的高)
//for循环:
g.fillRect(x, y, 100, 100);//实心的矩形
}
// anNiuDengWenzi:按钮等上的文字,就是点击绑定点击事件的按钮等后,
// 会获取上面的文字,传值到actionPerformed里面
@Override
public void actionPerformed(ActionEvent anNiuDengWenzi) {
if(anNiuDengWenzi.getActionCommand().equals("刷新")){
this.x+=10;this.y+=10;
// 每次点击按钮后就会改变这里的矩形的X轴方向位移和y轴方向位移,
// 都会加10
repaint();//用于刷新页面
// 调用该方法的三个情况:
// 1.页面初始化
// 2.显示调用repaint()方法
// 3.页面大小进行改变的时候
}
}
}



做出验证码效果:

package swing;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
public class yanZhengMa extends JFrame{
public static JButton anNiu=null;
public static void main(String[] args) {
//思路:先画一个背景矩形
//画4个数字
//画干扰线
//画干扰点
new yanZhengMa();
}
public yanZhengMa(){
// ————
//5个基本属性其中的三个:
this.setLayout(null);
this.setSize(500,500);
this.setLocationRelativeTo(null);
// ————
//设置最大的总页面的大小位置等:
huaTuCLASS huaTuCLASS=new huaTuCLASS();
huaTuCLASS.setBounds(0,0,500,500);
this.add(huaTuCLASS);
// ————
// 设置按钮:
anNiu=new JButton("没看清,换一张验证码");
anNiu.setBounds(165,210,170,20);
anNiu.addActionListener(huaTuCLASS);
this.add(anNiu);
// ————
//5个基本属性其中的二个:
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
class huaTuCLASS extends JPanel implements ActionListener{
public void paint(Graphics g){
// g.clearRect(195,140,110,50);
g.clearRect(0, 0, this.getWidth(), this.getHeight());
// 一般都页面刷新后清除原先的整个页面内容,不然,
// 不是左上角按钮等会到最左上角等,会有“重影”等,
// 原先的某些页面内容等。
// :clearRect方法用于页面刷新后清除原先的内容
// erWeiMa.anNiu.setBounds(0, 0, 70, 30);
// ————
//画一个矩形:
g.setColor(Color.black);
g.fillRect(195,140,110,50);
// ————
Random Random=new Random();
String String="0123456789abcdefghijklmnopqrstuvwxyzfjosdj"
+ "fiosmiosnfioudsjfiosdjfiodsjfosdjfiosdjfkodsfl";
//用toCharArray()将一个字符串转为字符数组:
char[] charArray=String.toCharArray();//toCharArray()将字符串转为字符数组
//设置字体的颜色随机:
Color[] colorArray={Color.red,Color.yellow,
Color.blue,Color.black,Color.green};
for(int i=0;i<4;i++){//用for循环4次
g.setFont(new Font("微软雅黑",Font.BOLD,
Random.nextInt(10)+20));
g.setColor(colorArray[Random.nextInt(colorArray.length)]);
String randomChar=charArray[Random.nextInt(String.length())+1]+"";
g.drawString(randomChar,i*20+10+200,Random.nextInt(10)+165);
}
// [Random.nextInt(String.length())+1]为charArray数组的下标
// ,这里的Random.nextInt范围含头不含尾
// 比如:Random Random=new Random();
// Random.nextInt(4)将产生0,1,2,3这4个数字中的任何随机一个数字
// ————
//干扰线部分:
for(int i=0;i<8;i++){
//绘制5条干扰线:
g.setColor(colorArray[Random.nextInt(colorArray.length)]);
g.drawLine(Random.nextInt(100)+200,Random.nextInt(30)+150,
Random.nextInt(100)+200,Random.nextInt(30)+150);
}
// ————
//干扰点部分:
for(int i=0;i<20;i++){
//绘制5条干扰线
g.setColor(colorArray[Random.nextInt(colorArray.length)]);
int x=Random.nextInt(100)+200;
int y= Random.nextInt(30)+150;
g.drawLine(x,y,x+1,y+1);
}
}
@Override
public void actionPerformed(ActionEvent anNiuDengWenzi) {
// TODO Auto-generated method stub
if(anNiuDengWenzi.getActionCommand().
equals("没看清,换一张验证码")){
// this.x+=10;this.y+=10;
// 每次点击按钮后就会改变这里的矩形的X轴方向位移和y轴方向位移,
// 都会加10
repaint();//用于刷新页面
// 调用该方法的三个情况:
// 1.页面初始化
// 2.显示调用repaint()方法
// 3.页面大小进行改变的时候
}
}
}



用键盘控制图片的上下左右的移动:

package swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class jianPanYiDong extends JFrame{
// jianPanYiDong:键盘移动
// public static JLabel tiShiWenZi;
// public static JButton anNiu;
public static void main(String[] args) {
new jianPanYiDong();
JOptionPane.showMessageDialog(null,"点击键盘上的W,图片向前\n"
+ "点击键盘上的S,图片向后\n"
+ "点击键盘上的A,图片向左\n"
+ "点击键盘上的D,图片向右");
}
public jianPanYiDong(){
this.setLayout(null);
this.setSize(500,500);
this.setLocationRelativeTo(null);
jianPanYiDonghuaTuCLass huaTuCLass=new jianPanYiDonghuaTuCLass();
huaTuCLass.setBounds(0,0,500,500);
this.add(huaTuCLass);
this.addKeyListener(huaTuCLass);
// __
// 设置提示文字(这里文字等控件的显示都没效果,
// 可能是因为设置了clearRect(清除矩形的范围)):
// tiShiWenZi=new JLabel("点击键盘上的W,图片向前\n"
// + "点击键盘上的S,图片向后\n"
// + "点击键盘上的A,图片向左\n"
// + "点击键盘上的D,图片向右");
// tiShiWenZi.setBounds(0,0,170,50);
// this.add(tiShiWenZi);
// anNiu = new JButton("没看清,换一张验证码");
// anNiu.setBounds(165,210,170,20);
//
// this.add(anNiu);
// __
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
//————
//用implements实现键盘点击的KeyListener接口:
class jianPanYiDonghuaTuCLass extends JPanel implements KeyListener{
// :jianPanYiDonghuaTuCLass:调用的这个类不可重名或只是大小写区别的命名等
// 不然会报错等
// ————
int x,y;
Image Image;
//在构造方法里初始化x轴,y轴方向的位置和图片:
public jianPanYiDonghuaTuCLass(){
x=100;
y=100;
Image=Toolkit.getDefaultToolkit().getImage("人.png");
}
//用paint绘制的方法绘制图片:
public void paint(Graphics g){
g.clearRect(0,0,this.getWidth(),this.getHeight());
g.drawImage(Image,x,y,100,100,this);
}
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
//点击键盘的方法:
if(e.getKeyCode()==KeyEvent.VK_W){
//点击一个键盘按钮后让图片移动 :
this.y-=10;
// JOptionPane.showMessageDialog(null,"点击了W");
}
if(e.getKeyCode()==KeyEvent.VK_S){
this.y+=10;
// JOptionPane.showMessageDialog(null,"点击了S");
}
if(e.getKeyCode()==KeyEvent.VK_A){
this.x-=10;
// JOptionPane.showMessageDialog(null,"点击了A");
}
if(e.getKeyCode()==KeyEvent.VK_D){
this.x+=10;
// JOptionPane.showMessageDialog(null,"点击了D");
}
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}


