绘图板程序设计及其具体实现 第三篇

工具包详细解析

(二) 输入处理工具类

SafeKeyboardInput类

SafeKeyboardInput类是一个安全的键盘输入处理类,实现了KeyListener接口。当由于种种原因导致帧速率过低时,普通的键盘输入处理可能会漏掉一些事件。本类中使用将所有接受到的键盘事件储存在一个数组中,当需要处理的时候再按照顺序依次处理所有的键盘事件,因此不会漏掉任何键盘事件。但是这样也存在一个问题,如果之前接受到的键盘事件不需要处理,则需要调用flush函数来清空之前接收到的键盘事件。

  • SafeKeyboardInput类字段一览表
修饰符 类型 名称 说明
private enum EventType 表示键盘事件类型的枚举类
private class Event 表示键盘事件的类
private LinkedList< Event> eventThread 接收到的键盘事件列表
private LinkedList< Event> gameThread 正在处理的键盘事件列表
private Event event 当前正在处理的键盘事件
private int[] polled 表示键盘中所有键的数组(共256个)
  • SafeKeyboardInput类方法一览表
修饰符 返回值 函数名 参数 说明
public SafeKeyboardInput () 默认构造函数
public synchronized boolean keyDown (int keyCode) 返回一个键是否被按下
public synchronized boolean keyDownOnce (int keyCode) 返回一个键是否有且被按下一次
public synchronized boolean processEvent () 处理事件,返回是否还有时间未处理
public Character getKeyTyped () 返回单击的字符
public synchronized void poll () 每帧调用,刷新待处理的键盘事件
public synchronized void flush () 清除之前未处理的所有事件
public synchronized void keyPressed (KeyEvent e) 键盘按下事件触发
public synchronized void keyReleased (KeyEvent e) 键盘释放事件触发
public synchronized void keyTyped (KeyEvent e) 键盘单击事件触发
  • SafeKeyboardInput类源代码
package Rendering.utils;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.LinkedList;

public class SafeKeyboardInput implements KeyListener {
    private enum EventType {
        PRESSED,
        RELEASED,
        TYPED,
    }

    private class Event {
        KeyEvent event;
        EventType type;

        public Event(KeyEvent event, EventType type) {
            this.event = event;
            this.type = type;
        }
    }

    private LinkedList<Event> eventThread = new LinkedList<Event>();
    private LinkedList<Event> gameThread = new LinkedList<Event>();
    private Event event = null;
    private int[] polled;

    public SafeKeyboardInput() {
        polled = new int[256];
    }

    public synchronized boolean keyDown(int keyCode) {
        return keyCode == event.event.getKeyCode() && polled[keyCode] > 0;
    }

    public synchronized boolean keyDownOnce(int keyCode) {
        return keyCode == event.event.getKeyCode() && polled[keyCode] == 1;
    }

    public synchronized boolean processEvent() {
        event = gameThread.poll();
        if (event != null) {
            int keyCode = event.event.getKeyCode();
            if (keyCode >= 0 && keyCode < polled.length) {
                if (event.type == EventType.PRESSED) {
                    polled[keyCode]++;
                } else if (event.type == EventType.RELEASED) {
                    polled[keyCode] = 0;
                }
            }
        }
        return event != null;
    }

    public Character getKeyTyped() {
        if (event.type != EventType.TYPED) {
            return null;
        } else {
            return event.event.getKeyChar();
        }
    }

    public synchronized void poll() {
        LinkedList<Event> swap = eventThread;
        eventThread = gameThread;
        gameThread = swap;
    }

    public synchronized void flush() {
        eventThread = new LinkedList<Event>();
        gameThread = new LinkedList<Event>();
    }

    public synchronized void keyPressed(KeyEvent e) {
        eventThread.add(new Event(e, EventType.PRESSED));
    }

    public synchronized void keyReleased(KeyEvent e) {
        eventThread.add(new Event(e, EventType.RELEASED));
    }

    public synchronized void keyTyped(KeyEvent e) {
        eventThread.add(new Event(e, EventType.TYPED));
    }
}

RelativeMouseInput类

RelativeMouseInput类是一个既可以处理绝对鼠标事件,还可以处理相对鼠标事件的鼠标事件处理类,实现了MouseListener接口, MouseMotionListener接口和MouseWheelListener接口。当设置relative字段为false时,处理绝对鼠标事件;设置relative字段为true时,处理相对鼠标事件。

  • RelativeMouseInput类字段一览表
修饰符 类型 名称 说明
private static final int BUTTON_COUNT 表示鼠标所有按键的数目(3)
private Point mousePos 鼠标当前帧的位置
private Point currentPos 鼠标的实时位置
private boolean[] mouse 存储鼠标的按键是否被按下的数组
private int[] polled 表示鼠标所有键的数组
private int notches 鼠标滚轮的转动距离
private int polledNotches 当前帧鼠标滚轮的转动距离
private int dx 鼠标相对上一帧移动的x值
private int dy 鼠标相对上一帧移动的y值
private Robot robot 自动实现移动鼠标
private Component component 鼠标所在的组件
private boolean relative 处理绝对或相对鼠标事件
  • RelativeMouseInput类方法一览表
修饰符 返回值 函数名 参数 说明
public RelativeMouseInput (Component component) 构造函数
public synchronized void poll () 每帧调用,刷新当前帧的鼠标位置和滚轮位置
public synchronized boolean isRelative () 返回是否为相对鼠标事件
public synchronized void setRelative (boolean relative) 更改绝对/相对鼠标事件
public synchronized Point getPosition () 返回鼠标当前帧的绝对位置/相对上一帧的位置
public synchronized int getNotches () 返回当前帧鼠标滚轮的转动距离
public synchronized boolean buttonDown (int button) 返回一个键是否被按下
public synchronized boolean buttonDownOnce (int button) 返回一个键是否有且被按下一次
public synchronized void mousePressed (MouseEvent e) 鼠标按下事件触发
public synchronized void mouseReleased (MouseEvent e) 鼠标释放事件触发
public void mouseClicked (MouseEvent e) 鼠标单击事件触发
public synchronized void mouseEntered (MouseEvent e) 鼠标进入事件触发
public synchronized void mouseExited (MouseEvent e) 鼠标移出事件触发
public synchronized void mouseDragged (MouseEvent e) 鼠标拖动事件触发
public synchronized void mouseMoved (MouseEvent e) 鼠标移动事件触发
public synchronized void mouseWheelMoved (MouseWheelEvent e)
private Point getComponentCenter () 返回鼠标所在的组件
private void centerMouse () 移动鼠标到所在组件的中央
public void moveMouse (Vector2f mousePos) 移动鼠标到组件的指定位置
  • RelativeMouseInput类源代码
package Rendering.utils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class RelativeMouseInput
        implements MouseListener, MouseMotionListener, MouseWheelListener {
    private static final int BUTTON_COUNT=3;
    private Point mousePos;
    private Point currentPos;
    private boolean[] mouse;
    private int[] polled;
    private int notches;
    private int polledNotches;
    private int dx, dy;
    private Robot robot;
    private Component component;
    private boolean relative;

    public RelativeMouseInput(Component component) {
        this.component = component;
        try {
            robot = new Robot();
        } catch (Exception e) {
            e.printStackTrace();
        }
        mousePos = new Point(0, 0);
        currentPos = new Point(0, 0);
        mouse = new boolean[BUTTON_COUNT];
        polled = new int[BUTTON_COUNT];
    }

    public synchronized void poll(){
        if (isRelative()) {
            mousePos = new Point(dx, dy);
        } else {
            mousePos = new Point(currentPos);
        }
        dx = dy = 0;
        polledNotches = notches;
        notches = 0;
        for (int i = 0; i < mouse.length; i++) {
            if (mouse[i]) {
                polled[i]++;
            } else {
                polled[i] = 0;
            }
        }
    }

    public synchronized boolean isRelative() {
        return relative;
    }

    public synchronized void setRelative(boolean relative) {
        this.relative = relative;
        if (relative) {
            centerMouse();
        }
    }

    public synchronized Point getPosition() {
        return mousePos;
    }

    public synchronized int getNotches() {
        return polledNotches;
    }

    public synchronized boolean buttonDown(int button) {
        return polled[button-1]>0;
    }

    public synchronized boolean buttonDownOnce(int button) {
        return polled[button-1]==1;
    }

    public synchronized void mousePressed(MouseEvent e) {
        int button=e.getButton()-1;
        if (button >= 0 && button < mouse.length) {
            mouse[button] = true;
        }
    }

    public synchronized void mouseReleased(MouseEvent e) {
        int button=e.getButton()-1;
        if (button >= 0 && button < mouse.length) {
            mouse[button] = false;
        }
    }

    public void mouseClicked(MouseEvent e) {
        //Not needed
    }

    public synchronized void mouseEntered(MouseEvent e) {
        mouseMoved(e);
    }

    public synchronized void mouseExited(MouseEvent e) {
        mouseMoved(e);
    }

    public synchronized void mouseDragged(MouseEvent e) {
        mouseMoved(e);
    }

    public synchronized void mouseMoved(MouseEvent e) {
        if (isRelative()) {
            Point p = e.getPoint();
            Point center = getComponentCenter();
            dx += p.x - center.x;
            dy += p.y - center.y;
            centerMouse();
        } else {
            currentPos = e.getPoint();
        }
    }

    public synchronized void mouseWheelMoved(MouseWheelEvent e) {
        notches += e.getWheelRotation();
    }

    private Point getComponentCenter() {
        int w = component.getWidth();
        int h = component.getHeight();
        return new Point(w / 2, h / 2);
    }

    private void centerMouse() {
        if (robot != null && component.isShowing()) {
            Point center = getComponentCenter();
            SwingUtilities.convertPointToScreen(center, component);
            robot.mouseMove(center.x, center.y);
        }
    }

    public void moveMouse(Vector2f mousePos) {
        if (robot != null && component.isShowing()) {
            Point tmp = new Point((int) mousePos.x, (int) mousePos.y);
            SwingUtilities.convertPointToScreen(tmp, component);
            robot.mouseMove(tmp.x, tmp.y);
        } else {
            JOptionPane.showMessageDialog(
                    component, "Can not support similar!!!",
                    "Warning", JOptionPane.INFORMATION_MESSAGE
            );
        }
    }
}

更多:

第一篇
第二篇
第三篇
第四篇
第五篇
第六篇
第七篇
源代码

猜你喜欢

转载自blog.csdn.net/qq_39384184/article/details/80594999