一、事件处理机制:
-当鼠标点在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();
}
});
}
}