Swing基础+飞机大战源码

一、GUI简介

GUI,图形用户界面。可以将计算机的功能直观的呈现出来。所以GUI需要操作系统和硬件的支持,GUI编程往往要处理移植性问题,Java的GUI编程相对有比较好的的可移植性。

  • 三要素:组件、容器、事件。

    • 组件:具有一定的功能模块,提供了公用的接口以便外部使用,有良好的可复用性;

    • 容器(窗体),是特殊的组件,容器中可以放置其他组件,并通过布局管理器,管理容器中的各组件的位置;

    • 事件:组件触发的动作事件,Java中不同事件由不同监听器处理,组件是事件源,而监听器主要用来监听来自指定事件源产生的动作事件。

  • Java的GUI功能主要集中在awt和swing两个包中。awt是GUI底层包。swing包是高层的封装,更容易移植。swing包中有很多swing组件

二、Swing简介

1.Swing组件

Swing组件是用java实现的轻量级(light- weight)组件,没有本地代码,不依赖操作系统的支持,其包含AWT可视化组件的替代组件。

Swing组件独立于本地窗口系统。

Swing组件是基于AWT构建的。

2.Swing的类层次结构

在javax.swing包中,定义了两种类型的组件:

  • 顶层容器(JFrame,JDialog)
  • 轻量级组件

swing组件绝大部分都是AWT的Container类的直接子类和间接子类。所以swing组件大部分也都是容器。

类层次结构图:


3.轻组件JComponent类结构(组件)

JComponent类是所有轻量组件的父类; JComponent类是java.awt包中容器类Container类的子类,因此所有的轻量组件也都是容器 : 

  

顶层容器

  • JFrame ,JDialog, JApplet,JWindow

普通容器(中间容器)

  • JPanel ,JScrollPane(滚动窗格),JSplitPane(分割窗体),JTabbedPane,JOptionPane

基本控件(实现人机交互的组件)

  • JButton,JTextField,JLabel ,JTextArea,JComboBox。 

Swing组件除了AbstractButton类之外都以J开头。

三、swing容器及组件使用

1.顶层容器

JFrame类继承java.awt创建的Frame类(窗体,也是重量容器),所以JFrame类及其子类创建的对象实体,是窗体(也 叫swing窗体),也是重量容器。

JFrame创建的swing窗体含有一个 内容面板的容器,不能直接将组件加到窗体中,应该加到内容面板中。

获取内容面板:可以通过swing窗体调用getContentPane() 方法,然后再设置内容面板的布局(默认是 BorderLayout布局)

特性:

  • 默认不可视;
  •  默认宽高为0;
  •  不能相互嵌套。

注: 在swing窗体的内容面板中尽量不要既有重量容器又有轻量组件,最好只使用轻量组件,否则可能会出现预想不到的问题。

package cn.gok;

import javax.swing.JFrame;

public class Demo01 {
	
	public static void main(String[] args) {
		JFrame jframe = new JFrame();
		// 设置变体
		jframe.setTitle("这个是我第一个java窗体");
		// 设置窗体大小
		jframe.setSize(800,800);
		//设置关闭模式  退出应用程序 
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//null表示居中显示在屏幕的中间
		jframe.setLocationRelativeTo(null);
		//设置是否可以改变窗体大小
		jframe.setResizable(false);
		//设置窗体是否可见
		jframe.setVisible(true);

	}

}

设置窗体是否可见一般放在最后,也就是前面的标题、大小等等都设置好了,再设置课间。 

2.中间容器

Jpanel,是JComponet的子类,因此JPanel是轻量级组件, 且JPanel可以容纳其它组件;我们称JPanel为中间容器,或者叫面板。

特性:

  • 需要加入顶层容器中才可见(JFrame/JDialog)
  • 默认可见 默认布局:Flowlayout;
  • 可以相互嵌套; 
package cn.gok;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestJPanel extends JPanel{
	
	public static void main(String[] args) {
		JFrame jframe = new JFrame();
		// 设置变体
		jframe.setTitle("这个是我第一个java窗体");
		// 设置窗体大小
		jframe.setSize(800,800);
		//设置关闭模式  退出应用程序 
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//null表示居中显示在屏幕的中间
		jframe.setLocationRelativeTo(null);
		//设置是否可以改变窗体大小
		jframe.setResizable(false);
		
		
		// 创建中间容器
		TestJPanel tp = new TestJPanel();
		//将中间容器添加到JFrame中
		jframe.add(tp);
		
		
		//设置窗体是否可见
		jframe.setVisible(true);

	}

}

可以通过继承JFrame或者继承JPanel来创建一个窗体,继承JFrame,则窗体是顶层容器,需要将JPanel放入该窗体,继承JPanel,则窗体是中间容器,需要将该窗体放入顶层容器。 

 JFrame就好比画板一样,JPanel就好比画纸,各大组件就好比花花草草,将画纸放在画板上,然后在画纸里面绘制花花草草,也就是必须将JPanel放在JFrame中,然后在JPanel中绘制组件。

// 创建按钮
JButton button1 = new JButton("按钮1");
JButton button2 = new JButton("按钮2");
// 将按钮直接添加到顶层容器(JFrame)
jframe.add(button1);
jframe.add(button2);

 

会发现直接将组件添加到顶层容器(JFrame)中,组件会占据整个面板,而且后添加的会覆盖前面的。 

// 创建按钮
JButton button1 = new JButton("按钮1");
JButton button2 = new JButton("按钮2");
						
// 创建中间容器
TestJPanel tp = new TestJPanel();
//将中间容器添加到JFrame中
jframe.add(tp);
		
// 将按钮添加到中间容器中
tp.add(button1);
tp.add(button2);

 

先将中间容器放在顶层容器,再将组件放在中间容器,就可以避免该问题。 

 3.基本组件

JButton 生成按钮

  • 构造函数: public JButton(); public JButton(String tag);
  • 设置/获取按钮内容 public void setText(String tag); public String getText();

JTextField 生成单行文本框

  • 构造函数 public JTextField(); public JTextField(int cols);
  • 存/取文本框内容public void setText(String tag); public String getText();

JTextArea 生成多行文本框

  • 构造函数 public JTextArea (); public JTextArea (int rows, int cols); public JTextArea (String text, int rows, int cols);
  • 存/取文本框内容public void setText(String tag); public String getText(); public void append(String str);

JLable 生成标签

  • 构造函数 public JLabel(); public JLabel(String tag);
  • 存取public void setText(String tag); public String getText(); 

通用方法 :

所有swing组件都具有设置图标颜色字体大小边框的功能:

  • setIcon(Icon icon); //设置其上显示的图标.
  • setBackground(Color c); //设置背景色.
  • setForeground(Color c); //设置其上文字颜色.
  • setFont(Font font); //设置字体.
  • setPreferredSize(Dimension ds); //设置大小.
  • setBorder(Border bd); //设置边框.
  • setEnable(boolean b); //是否可用.
  • setEditable(boolean b); //是否可编辑

相关类:

  • Icon / ImageIcon //图标相关类
    • Icon icon1=new ImageIcon(“图片路径”);
  • Color //颜色相关类
    • Color color1=new Color(255,0,0); //红色
  • Font //字体相关类
    • Font font1=new Font(“隶书”, Font.BOLD,16);
  • Dimension //大小相关类
    • Dimension dim1=new Dimension(宽,高)
        // 创建按钮
		JButton button1 = new JButton("按钮1");
		JButton button2 = new JButton("按钮2");
		// 创建文本框
		JTextField textField = new JTextField("文本框");
		// 创建标签
		JLabel label = new JLabel("标签");
		// 创建文本域
		JTextArea textArea = new JTextArea("文本域");
		
		// 设置按钮字体颜色
		button1.setForeground(new Color(255,0,0));
		// 设置文本框字体
		textField.setFont(new Font("楷体", Font.BOLD, 16));
		// 设置文本框大小
		textField.setPreferredSize(new Dimension(100,50));
				
		// 创建中间容器
		TestJPanel tp = new TestJPanel();
		//将中间容器添加到JFrame中
		jframe.add(tp);
		
		// 将按钮添加到中间容器中
		tp.add(button1);
		tp.add(button2);
		tp.add(textField);
		tp.add(label);
		tp.add(textArea);

 

四、绘制图像

重写容器的paint方法实现绘制背景图像, 工具类Graphics,在背景图片上再绘制图片,绘制字符串等功能。
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
}
    @Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);
		// 设置画笔颜色,字体等等
		g.setColor(Color.RED);
		g.setFont(new Font("宋体", Font.ITALIC, 25));
		//绘制背景图片【放在最前面绘制】
		Image imageBG = new ImageIcon("image/background.jpg").getImage();
		g.drawImage(imageBG, 0, 0, this);				
		g.drawLine(10, 10, 50, 50);//绘制直线
		g.drawRect(50, 50, 100, 80);//绘制矩形
		g.fillRect(50, 50, 100, 80);
		g.drawArc(10, 150, 50, 80, 0, 360);	//绘制圆形
		g.setFont(new Font("隶书", Font.BOLD, 36));	//绘制字符串
		g.drawString("游戏结束....",60, 160);
		Image image = new ImageIcon("image/assisent1_1.png").getImage();
		g.drawImage(image, 200, 200, this);
		Image image2 = new ImageIcon("image/assisent1_1.png").getImage();
		g.drawImage(image2, 248, 200, this);
	}

 

总结:

  • 工具类Graphics
  • 在背景图片上再绘制图片
  • 绘制字符串等功能 音频、图片等都属于静态资源,可以在类中定义静态变量,并在静态块中赋予他们初始值,以便类加载时就能首先将静态资源先缓存起来,之后功能调用和使用可以优化系统的加载
  • 画纸JPanel必须存在于画板JFrame中,才能使用,而组件则在画纸中使用。
  • 画板JFrame若不设置的话则默认不可见,所以当新建JFrame对象实体需要进行设置。 

五、事件处理

1.事件处理基本概念 

正常情况,组件(事件源)都不处理自己的事件,而是将事件处理委托给外部实体(监听器),这种事件处理模型称为 事 件的授权处理模型 。不同的事件可以交由不同类型的监听器去处理。

事件处理过程,涉及三类对象:

  • Event -事件,用户对界面操作在java语言上的描述,以类的形式出现,例如键盘操作对应的事件类是KeyEvent。
  • Event Source -事件源,事件发生的场所,通常就是各个组件,例如按钮JButton。
  • Event handler -事件处理者,接收事件对象并对其进行处理 事件处理过程,

涉及三种角色:

  • 事件源
  • 监听器
  • 处理事件的接口(适配器)

实现事件处理步骤:

  1. 找到事件源(按钮、文本框等组件)
  2. 创建监听器对象(需要实现相应接口的类) -->或者说实现监听器的适配器
  3. 为事件源注册监听器对象 --> 事件源(组件).add...Listener(适配器)

事件实现方式(适配器Adapter)

  • 在java事件处理中,当处理事件的接口中多于一个方法时,系统就会提供相应的实现类(这个是抽象的),这样的实现类我 们称为适配器类。
  • 用内部类实现事件处理,一般监视器类我们可以内部类或匿名类实现.
  • 用外部类实现事件处理 
package cn.gok;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Demo03 extends JFrame{
	
	public Demo03() {
		
		// 设置变体
		this.setTitle("这个是我第一个java窗体");
		// 设置窗体大小
		this.setSize(800,800);
		//设置关闭模式  退出应用程序 
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//null表示居中显示在屏幕的中间
		this.setLocationRelativeTo(null);
		//设置是否可以改变窗体大小
		this.setResizable(false);
		
		// 添加中间容器
		this.body();
	
		//设置窗体是否可见
		this.setVisible(true);

	}
	
	public void body() {
		JPanel jPanel = new JPanel();
		
		JButton button1 = new JButton("按钮1");
		JButton button2 = new JButton("按钮2");
		JTextField textField = new JTextField(10);
		
		// 创建监听事件
		MyActionListener actionListener = new MyActionListener(textField);
		// 给按钮绑定监听事件
		button1.addActionListener(actionListener);
		button2.addActionListener(actionListener);
		
		jPanel.add(button1);		
		jPanel.add(button2);	
		jPanel.add(textField);	
		
		
		this.add(jPanel);
	
	}
	
	public static void main(String[] args) {
		new Demo03();
	}
	
	
	// 内部类
	class MyActionListener implements ActionListener{
		JTextField field;
		
		public MyActionListener(JTextField field) {
			this.field = field;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			// 获取事件源
			Object obj = e.getSource();
			// 判断是否是按钮事件源
			if(obj instanceof JButton) {
				JButton button = (JButton)obj;
				// 获取按钮文本
				String text = button.getText();
				// 给文本框设置文本
				field.setText(text);
			}
		}
	}
}

  

2.鼠标处理事件 

Java种有两个不同接口处理:

  • MouseListener 可处理事件(MouseEvent):--> 对应适配器 MouseAdapter
        // 采用匿名内部类添加鼠标事件
		jLabel.addMouseListener(new MouseListener() {
			
			@Override
			public void mouseReleased(MouseEvent e) {
				System.out.println("鼠标释放事件");
				
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
				System.out.println("鼠标按压事件");
				
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("鼠标移出事件");
				
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("鼠标进入事件");
				
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("鼠标点击事件");
				
			}
		});

通过 组件名.addMouseListener 的方法,为组件绑定鼠标添加事件。

package cn.gok;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Demo04 extends JPanel{
	
	public Demo04() {
		JLabel jLabel = new JLabel();
		Icon icon1 = new ImageIcon("image/serverstart.gif");
		Icon icon2 = new ImageIcon("image/serverstop.gif");
		jLabel.setIcon(icon1);
		this.add(jLabel);
		
		// 采用匿名内部类添加鼠标事件
		jLabel.addMouseListener(new MouseListener() {
			
			@Override
			public void mouseReleased(MouseEvent e) {
				System.out.println("鼠标释放事件");
				
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
				System.out.println("鼠标按压事件");
				
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("鼠标移出事件");
				jLabel.setIcon(icon1);
				
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("鼠标进入事件");
				jLabel.setIcon(icon2);
				
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("鼠标点击事件");
				
			}
		});
		
		this.init();
	}
	
	public void init() {
		JFrame jframe = new JFrame();
		// 设置变体
		jframe.setTitle("这个是我第一个java窗体");
		// 设置窗体大小
		jframe.setSize(500,500);
		//设置关闭模式  退出应用程序 
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//null表示居中显示在屏幕的中间
		jframe.setLocationRelativeTo(null);
		//设置是否可以改变窗体大小
		jframe.setResizable(false);
		
		// 中间容器添加到顶层容器
		jframe.add(this);
		
		//设置窗体是否可见
		jframe.setVisible(true);
	}
	
	public static void main(String[] args) {
		new Demo04();
	}

}

 

  • MouseMotionListener可处理事件(MouseEvent):--> 对应适配器 MouseMotionAdapter
    • 鼠标按键在组件上按下并拖动 --> mouseDragged
    • 光标移动到组件上 但无按键按下 --> mouseMoved
    • 获取鼠标相关信息的方法
      • int getClickCount(); //返回鼠标单击次数
      • Point getPoint(); //返回事件相对于源组件的x,y坐标
      • int getX(); /int getY(); //获取x或y的坐标
      • void translatePoint(int x, int y); //将事件的坐标平移到新位置,其中x,y为原坐标的偏移量。 
    jLabel.addMouseMotionListener(new MouseMotionListener() {
			
			@Override
			public void mouseMoved(MouseEvent e) {
				System.out.println("鼠标移动事件");
				System.out.println(e.getPoint());
			}
			
			@Override
			public void mouseDragged(MouseEvent e) {
				System.out.println("鼠标拖动事件");
				System.out.println(e.getX()+","+e.getY());
			}
		});

 

移动事件:鼠标进入组件,不需要按下,移动鼠标即可触发。

拖动事件:鼠标进入组件,需要按下不放才可触发。 

通过MouseAdapter指定(重写)选择想要哪个鼠标监听事件。

 

    MouseAdapter adapter = new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("鼠标点击");
			}
			
			@Override
			public void mouseMoved(MouseEvent e) {
				System.out.println("鼠标移动");
			}
		};
		// 两种都需要绑定
		jLabel.addMouseListener(adapter);
		jLabel.addMouseMotionListener(adapter);

MouseAdapter中若包含了以上两种的鼠标监听事件,则两种都需要绑定给组件,否则不起作用。 

六、定时任务组件 

javax.swing.Timer //在指定延迟之后激发一个或多个操作事件,实现定时功能。

  • void start();;//开始Timercancel()
  • void stop();//停止Timercancel();

 

package cn.gok;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;

public class Demo05 extends JPanel{
	
	int num = 0;
	
	public Demo05() {
		
		JButton button1 = new JButton("开始");
		JButton button2 = new JButton("结束");
		// 禁用按钮2
		button2.setEnabled(false);
		JTextField field = new JTextField("0");
		field.setPreferredSize(new Dimension(100,30));
		
		
		// 定时器
		Timer timer = new Timer(1000, new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				field.setText(num+"");
				num++;
			}
		});
		
		
		
		
		MouseAdapter adapter = new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				Object obj = e.getSource();
				if(obj instanceof JButton) {
					JButton button = (JButton)obj;
					String text = button.getText();
					if("开始".equals(text)) {
						// 禁用按钮1
						button1.setEnabled(false);
						// 启动按钮2
						button2.setEnabled(true);
						// 开启定时器
						timer.start();
					}else if("结束".equals(text)) {
						
						// 文本框设置为0
						num = 0;
						field.setText(num+"");					
						// 禁用按钮2
						button2.setEnabled(false);
						// 启动按钮1
						button1.setEnabled(true);
						// 关闭定时器
						timer.stop();
						
					}
					
				}
			}
		};
		
		button1.addMouseListener(adapter);
		button2.addMouseListener(adapter);
		
		this.add(button1);
		this.add(button2);
		this.add(field);
		
		
		this.init();
	}
	
	public void init() {
		JFrame jframe = new JFrame();
		// 设置变体
		jframe.setTitle("这个是我第一个java窗体");
		// 设置窗体大小
		jframe.setSize(500,500);
		//设置关闭模式  退出应用程序 
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//null表示居中显示在屏幕的中间
		jframe.setLocationRelativeTo(null);
		//设置是否可以改变窗体大小
		jframe.setResizable(false);
		
		// 中间容器添加到顶层容器
		jframe.add(this);
		
		//设置窗体是否可见
		jframe.setVisible(true);
	}
	
	public static void main(String[] args) {
		
		
		
		new Demo05();
	}

}

 

总结: 

上面基本上已经将Java中关于Swing的一些常用操作介绍完了,接着试试做一个小小的项目看看吧。下面是关于飞机大战项目的效果和源码。

  

 项目源码:https://download.youkuaiyun.com/download/x_q_x_/87261275

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.Thinking.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值