【Java AWT 图形界面编程】使用小键盘按键缩放 Canvas 画布中绘制的背景图像 ( 键盘按键监听 + 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )

2023-05-09 17:48:04 浏览数 (2)

一、键盘按键监听 - 要点分析


如果要为 Java AWT 界面编程的应用设置键盘按键监听 , 必须为 Frame / JFrame 窗口设置键盘监听 , 为组件设置是无效的 ;

下面是设置键盘监听的核心代码 , 必须要为窗口设置键盘监听 ;

代码语言:javascript复制
        frame.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() >= KeyEvent.VK_NUMPAD1 && e.getKeyCode() <= KeyEvent.VK_NUMPAD9) {
                    // 根据按键计算出缩放比例
                    scale = e.getKeyCode() - 96;

                    // 基于鼠标位置和比例, 计算最新的偏移
                    restore();
                    repaint();  // 重新绘制画布
                }
            }
        });

二、键盘按键监听 绘制超大图像 鼠标拖动 鼠标滚轮缩放 以当前鼠标指针位置为缩放中心 示例


在 【Java AWT 图形界面编程】Canvas 中绘制超大图片 ( 使用鼠标拖动查看全图 | 设置 JFrame 窗口自动关闭 | 获取并绘制图片 | 鼠标拖动计算位移 | 画布偏移 ) 博客中 , 绘制了超大图像 , 可以使用鼠标拖动 ;

在 【Java AWT 图形界面编程】使用鼠标滚轮放大缩小 Canvas 画布 ( 鼠标滚轮事件监听器 MouseWheelListener ) 博客中 , 新增鼠标滚轮缩放画布示例 , 但是使用鼠标拖动时 , 拖动的效果也随之缩放, 如 缩小画布后 , 移动鼠标 , 移动距离对应的缩放效果也随之缩小 ;

在 【Java AWT 图形界面编程】使用鼠标滚轮放大缩小 Canvas 画布中绘制的背景图像 ( 鼠标滚轮事件监听器 MouseWheelListener | Canvas 中绘制图像并设置图像大小 ) 博客中 , 使用缩放背景图像的方式 , 实现缩放效果 , 并同时福袋鼠标指针拖拽效果 ;

本博客中实现的案例 , 在上面的基础上 , 添加了鼠标滚轮缩放的中心点设置为当前鼠标中心点 ;

1、代码示例

代码语言:javascript复制
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class LargeCanvas extends JPanel {

    // 鼠标按下时的坐标 以及 更新后的坐标
    private int startX, startY;

    // 当前的位置偏移
    private int offsetX = 0, offsetY = 0;

    // 缩放比例,默认为 1.0
    private double scale = 1.0;

    private Image image;

    public double pointer_ratio_x;
    public double pointer_ratio_y;

    public int pointer_x;
    public int pointer_y;

    public LargeCanvas() {
        // 画布大小设置为 800 x 600
        // 绘制的图片是 2K 大小的图片
        setPreferredSize(new Dimension(800, 600));

        // 添加鼠标滚轮监听器
        addMouseWheelListener(new MouseWheelListener() {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                // 保存当前的鼠标位置及比例
                save(e.getX(), e.getY());
                int notches = e.getWheelRotation();
                if (notches < 0) {
                    // 滚轮向上,放大画布
                    scale *= 1.1;
                } else {
                    // 滚轮向下,缩小画布
                    scale /= 1.1;
                }
                // 基于鼠标位置和比例, 计算最新的偏移
                restore();
                repaint();  // 重新绘制画布
            }
        });

        // 为组件设置鼠标监听事件
        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                // 记录鼠标按下时的坐标
                startX = e.getX();
                startY = e.getY();

                // 保存当前的鼠标位置及比例
                save(e.getX(), e.getY());
            }
        });

        // 添加鼠标动作监听
        addMouseMotionListener(new MouseAdapter() {
            // 鼠标拖动事件
            public void mouseDragged(MouseEvent e) {
                // 统计本次鼠标移动的相对值
                int dx = e.getX() - startX;
                int dy = e.getY() - startY;

                // 偏移量累加
                offsetX  = dx;
                offsetY  = dy;

                // 重新绘图
                repaint();

                // 记录当前拖动后的位置
                startX  = dx;
                startY  = dy;
            }
        });
    }

    /**
     * 记录滚轮缩放时鼠标指针状态
     */
    public void save(int x, int y){
        // 记录鼠标坐标
        pointer_x = x;
        pointer_y = y;

        // 计算画布
        double canvasX = x - offsetX;
        double canvasY = y - offsetY;

        // 计算图片大小
        double imageWidth = image.getWidth(null) * scale;  // 缩放后的图像宽度
        double imageHeight = image.getHeight(null) * scale;  // 缩放后的图像高度

        // 计算比例
        pointer_ratio_x = canvasX / imageWidth ;
        pointer_ratio_y = canvasY / imageHeight ;
    }

    /**
     * 计算新的比例
     */
    public void restore(){
        // 缩放后的尺寸
        double imageWidth = image.getWidth(null) * scale;  // 缩放后的图像宽度
        double imageHeight = image.getHeight(null) * scale;  // 缩放后的图像高度

        // 计算整张画布宽度
        double canvasX = imageWidth * pointer_ratio_x;
        double canvasY = imageHeight * pointer_ratio_y;

        // 计算画布偏移
        offsetX = (int) (pointer_x - canvasX);
        offsetY = (int) (pointer_y - canvasY);
    }

    public void initKeyListener(JFrame frame) {
        frame.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() >= KeyEvent.VK_NUMPAD1 && e.getKeyCode() <= KeyEvent.VK_NUMPAD9) {
                    // 根据按键计算出缩放比例
                    scale = e.getKeyCode() - 96;

                    // 基于鼠标位置和比例, 计算最新的偏移
                    restore();
                    repaint();  // 重新绘制画布
                }
            }
        });
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        // 画布进行整体偏移
        Graphics2D g2 = (Graphics2D)g;

        // 缩放画布
        //g2.scale(scale, scale);

        // 拖动画布
        g2.translate(offsetX, offsetY);

        // 获取图片
        this.image = Toolkit.getDefaultToolkit().getImage("image.jpg");

        // 绘制图形
        //g2.drawImage(image, 0, 0, this);

        // 绘制图像
        int imageWidth = (int) (image.getWidth(null) * scale);  // 缩放后的图像宽度
        int imageHeight = (int) (image.getHeight(null) * scale);  // 缩放后的图像高度
        g2.drawImage(image, 0, 0, imageWidth, imageHeight, null);
    }

    public static void main(String[] args) {
        // 创建 JFrame 窗口
        JFrame frame = new JFrame("Large Canvas");

        // 设置窗口关闭行为 点击右上角关闭按钮 关闭窗口并退出应用
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 创建画布
        LargeCanvas canvas = new LargeCanvas();

        // 将画布放入滚动布局
        JScrollPane scrollPane = new JScrollPane(canvas);

        // 将滚动布局放入窗口
        frame.getContentPane().add(scrollPane);

        // 窗口自适应
        frame.pack();

        // 窗口设置可见
        frame.setVisible(true);

        // 设置键盘监听时间
        canvas.initKeyListener(frame);
    }
}

2、执行效果

执行后 , 将图像中船头的 H 标识放置在界面中心 ;

将鼠标指针放在 H 位置 , 点击一次 , 按下数字键 9 , 放大 9 倍的效果如下 :

0 人点赞