Swing-事件处理机制详解

一、事件处理机制:

 -当鼠标点在B3时,

B3有机会处理

B2次之

B1最后

如果B3处理了事件,则B2,B1均无机会

**SWing事件处理机制

1、子控件最有机会处理

2、如果子控件未处理,则父控件才有机会

二、鼠标事件

定义鼠标事件的三种方法:

1、监听器addXXXListener()

	//第1种方式
	private class MyPanel extends JPanel
	{
		public MyPanel()
		{
			this.addMouseListener(new MouseAdapter() {

				@Override
				public void mouseClicked(MouseEvent e) {
					System.out.println("First MouseListener点击位置:"+e.getPoint());
				}
				
			});
		}
	}

2、重写processXXXXEvent()

	//第2种方式
	private class MyPanel extends JPanel
	{
		public MyPanel()
		{
			//第2种方式,先enableEvents();确保能够响应鼠标事件
					 // 后processMouseEvent ,来判断处理分析属于哪种鼠标事件
			this.enableEvents(MouseEvent.MOUSE_EVENT_MASK);
		}

		@Override
		protected void processMouseEvent(MouseEvent e) {
			if(e.getID()==MouseEvent.MOUSE_CLICKED)
			{
				System.out.println("Second MouseListener点击位置:"+e.getPoint());
			}
		}
		
	}

3、全局事件监听


    这种方式是注册一个全局的监听器,当前程序里所有界面时间都会发给他处理,因此效率会低一些,
    在处理特殊需求的时候可以考虑
    
    注意:如果用户没有点中本程序窗口,点了其他程序窗口,或者点了桌面,那么这个鼠标事件自然是收不到的

	private class MyPanel extends JPanel
	{
		public MyPanel()
		{
			this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
		}
		
		AWTEventListener listener=new AWTEventListener() {

			@Override
			public void eventDispatched(AWTEvent event) {
				if(event instanceof MouseEvent)
				{
					if(event.getID()==MouseEvent.MOUSE_PRESSED)
					{
						MouseEvent e=(MouseEvent)event;
						System.out.println("全局事件监听器:"+e.getPoint());
						
						if(e.getSource()==root) //自己判断一下是点中了哪一个控件
						{
							
						}
					}

				}
				
			}
			
		};
	}
	

注:一般就用第一个就OK了,因为一般情况下都是普通的事件监听器

三、键盘事件

添加一个自定义控件,添加键盘事件支持,当在键盘上按下一个键时,触发三个事件

KEY_PRESSED

KEY_TYPED

KEY_RELEASED

只有字符会有KEY_RELEASED事件,控制键没有

 

键值:

KeyEvent.getKeyCode()   

......例如:VK_F1,VK_2,VK_LEFT
字符:KeyEvent.getKeyChar() 
判断CTRL:KeyEvent.isControlDown() 
判断ALT:KeyEvent.isAltDown() 
判断SHIFT:KeyEvent.isShiftDown() 

注意:

1、自定义控件默认是不支持键盘的输入的

需要this.setFocusable(true); //允许输入

2、控件默认也是没有焦点的

并且需要点一下,才能进入键盘输入(就像TextField一样)

也可以用requestFocusInWindows()来申请焦点

 

测试代码:

package my;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

public class MyPanel extends JPanel
{
	public MyPanel()
	{
		this.setFocusable(true); //允许输入
		this.enableEvents(KeyEvent.MOUSE_EVENT_MASK);  //添加允许的事件...
		this.enableEvents(KeyEvent.KEY_EVENT_MASK);
	}

	@Override
	protected void processKeyEvent(KeyEvent e) 
	{
		if(e.getID()==KeyEvent.KEY_PRESSED)
		{
			int code=e.getKeyCode();
			if(code==KeyEvent.VK_F1)
			{
				System.out.println("F1 is pressed");	
			}
			
			System.out.println("KeyCode: " + code);	
		}
		
		if(e.getID()==KeyEvent.KEY_TYPED)
		{
			char ch=e.getKeyChar();
			System.out.println("输入了字符:"+ch);
		
		}
		super.processKeyEvent(e);
	}

	@Override//鼠标事件
	protected void processMouseEvent(MouseEvent e) {
		if(e.getID()==MouseEvent.MOUSE_CLICKED)  //如果点击了,面板进入可输入状态
		{
			this.repaint();
		}
		super.processMouseEvent(e);
	}

	@Override
	protected void paintComponent(Graphics g) 
	{
		int width=this.getWidth();
		int height=this.getHeight();
		Graphics2D g2d=(Graphics2D)g;
		g2d.clearRect(0, 0, width, height);
		
		// 平滑绘制 ( 反锯齿 )
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2d.setFont(new Font("宋体", Font.BOLD, 20));
		
		//hasFocus()判断当前是否有输入焦点
		if(this.hasFocus())
		{
			g2d.setColor(Color.YELLOW);
			g2d.fillRect(0, 0, width, height);	
			g2d.setColor(Color.BLACK);
			g2d.drawString("可以在此输入 ...", 50, 50);
		}
		else
		{
			g2d.setColor(Color.WHITE);
			g2d.fillRect(0, 0, width, height);	
			g2d.setColor(Color.BLACK);
			g2d.drawString("请先点我,然后才可以输入~~", 50, 50);
		}
	}
		
}
package my;

import java.awt.AWTEvent;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

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

public class MyFrame extends JFrame
{
	MyPanel root=new MyPanel();
	
	public MyFrame(String title)
	{
		super(title);
		

		this.setContentPane(root);
		root.setLayout(null);
	}
	
}


package my;

import java.awt.Container;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Demo
{
	private static void createGUI()
	{
		// JFrame指一个窗口,构造方法的参数为窗口标题
		// 语法:因为MyFrame是JFrame的子类,所以可以这么写
		JFrame frame = new MyFrame("Swing Demo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		// 设置窗口的其他参数,如窗口大小
		frame.setSize(700, 450);
		
		// 显示窗口
		frame.setVisible(true);
		
		
	}
	
	public static void main(String[] args)
	{
		//设置界面样式 Look And Feel
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
				| UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run()
			{
				createGUI();
			}
		});
 
	}
}

四、键盘控制方块移动

只能静态演示

 设计目的:练手鼠标点击以及键盘事件

设计思路:

1、确定方框的范围

2、添加鼠标点击事件(当点击时,进入游戏状态)

3、添加键盘事件(①当点击键盘时,进入游戏状态,②上下左右由键盘来控制,③键盘事件一次,重新绘制一次

4、在键盘控制下确定方框移动方向以及边界(这里的方框是用二维数组来表示,一个[][]代表一个位置,位置用坐标来表示)

*绘制+定位*

package my;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

public class MyPanel extends JPanel
{
	private int NN=5; //4×4网格
	
	int curRow,curCol; //当前位置
	Rectangle area;  //中间可玩区域(正方形)
	Rectangle[][] grid=new Rectangle[NN][NN];//每个单元格
	
	
	public MyPanel()
	{
		this.setFocusable(true); //允许输入
		this.enableEvents(KeyEvent.MOUSE_EVENT_MASK);  //添加允许的事件...
		this.enableEvents(KeyEvent.KEY_EVENT_MASK);
	}

	@Override
	protected void processKeyEvent(KeyEvent e) 
	{
		if(e.getID()==KeyEvent.KEY_PRESSED)
		{
			int code=e.getKeyCode();
			System.out.println("KeyCode: " + code);	
			
			//响应上、下、左、右
			if(code == KeyEvent.VK_UP)
				curRow -= 1;
			else if(code == KeyEvent.VK_DOWN)
				curRow += 1;
			else if(code == KeyEvent.VK_LEFT)
				curCol -= 1;
			else if(code == KeyEvent.VK_RIGHT)
				curCol += 1;
			
			//位置检测,(是否已经到边缘)
			if(curRow <0) curRow = 0;
			if(curRow >= NN) curRow = NN - 1;
			if(curCol <0) curCol = 0;
			if(curCol >= NN) curCol = NN - 1;	
			
			//重绘
			repaint();
		}
		
		super.processKeyEvent(e);
	}

	@Override//鼠标事件
	protected void processMouseEvent(MouseEvent e) {
		if(e.getID()==MouseEvent.MOUSE_CLICKED)  //如果点击了,面板进入可输入状态
		{
			this.repaint();
		}
		super.processMouseEvent(e);
	}
	
	private void calculate()
	{
		int width=getWidth();
		int height=getHeight();
		System.out.println("宽:"+width+"长:"+height);
		//中间取一个正方形
		int size=width<height?width:height;
		size=size-4; //缩小一点
		if(size>200)size=200;  //最大尺寸200
		
		int centerX=(width-size)/2;
		int centerY=(height-size)/2;  //中心点
		area=new Rectangle(centerX,centerY,size,size);
		
		//每一个小格子的尺寸
		int unit=area.width/NN;
		
		//计算出每个单元格
		for(int row=0;row<NN;row++) //行
		{
			for(int col=0;col<NN;col++)
			{
				int x=(int)(area.x+col*unit);
				int y=(int)(area.y+row*unit);
				
				grid[row][col] = new Rectangle(x,y,unit,unit);
				grid[row][col].grow(-2, -2); // 缩一点	
			}
		}
		
	}

	@Override
	protected void paintComponent(Graphics g) 
	{
		int width=this.getWidth();
		int height=this.getHeight();
		Graphics2D g2d=(Graphics2D)g;
		g2d.clearRect(0, 0, width, height);
		
		// 平滑绘制 ( 反锯齿 )
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
								RenderingHints.VALUE_ANTIALIAS_ON);
		
		calculate();
		System.out.println("row=" + curRow+ "," + curCol);
		
		// 两种颜色:焦点色 与 无焦点状态
		Color focusColor = new Color(0x1E90FF);
		Color darkColor = new Color(0xAAAAAA);
		
		// 填充白色
		g2d.setPaint(Color.WHITE);
		g2d.fill(area);
		
		//画边框
		if(this.isFocusOwner())
			g2d.setPaint(focusColor);
		else
			g2d.setPaint(darkColor);
		g2d.setStroke( new BasicStroke(1));
		g2d.draw(area);
		
		// 绘制当前的位置(箱子的位置)		
		for(int i=0; i<NN; i++)
		{
			for(int k=0; k<NN; k++)
			{
				Rectangle cell = grid[i][k];
				if(i == curRow && k== curCol)
				{	
					//g2d.setPaint(focusColor);
					g2d.fill( cell);
				}
			}
		}		
	}
		
}
package my;

import java.awt.AWTEvent;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

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

public class MyFrame extends JFrame
{
	MyPanel root=new MyPanel();
	
	public MyFrame(String title)
	{
		super(title);
		

		this.setContentPane(root);
		root.setLayout(null);
	}
	
}


package my;

import java.awt.Container;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Demo
{
	private static void createGUI()
	{
		// JFrame指一个窗口,构造方法的参数为窗口标题
		// 语法:因为MyFrame是JFrame的子类,所以可以这么写
		JFrame frame = new MyFrame("推动");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		// 设置窗口的其他参数,如窗口大小
		frame.setSize(800, 500);
		
		// 显示窗口
		frame.setVisible(true);
		
		
	}
	
	public static void main(String[] args)
	{
		//设置界面样式 Look And Feel
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
				| UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run()
			{
				createGUI();
			}
		});
 
	}
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值