文章目录

  • 一、鼠标滚轮缩放的中心点设置为当前鼠标中心点 - 要点分析
    • 1、保存当前鼠标指针指向的位置
    • 2、根据鼠标指针指向的位置以及比例重新计算图片位置
  • 二、绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例
    • 1、代码示例
    • 2、执行效果

一、鼠标滚轮缩放的中心点设置为当前鼠标中心点 - 要点分析


鼠标指针指向界面中的 Canvas 画布某个位置 , Canvas 画布中绘制着一张超大图片 , 以该位置为中心 , 滑动鼠标滚轮时进行缩放 ;

使用鼠标滚轮缩放后 , 在 Canvas 中绘制的图片的尺寸肯定是放大或者缩小了 , 尺寸发生了改变 ;

图片缩放时 , 鼠标指针指向一个位置 , 该位置对应着一个当前 Canvas 画布中的 x, y 坐标 , 同时可以计算出当前位置对应的图片中的 水平方向的比例 和 垂直方向的比例 ;

在缩放后的图片中 , 只要保证鼠标指针指向相同的 x, y 坐标时 , 该位置对应的 水平方向的比例 和 垂直方向的比例 仍然保持不变 , 那就需要移动图片的位置 ;

  • 如果放大图片就需要将图片往左上方移动 ;
  • 如果缩小图片就需要将图片往右下方移动 ;

此时可以分析出 , 如果要实现 鼠标滚轮缩放的中心点设置为当前鼠标中心点 , 需要进行下面两个步骤的操作 :

  • 保存当前鼠标指针指向的位置 , 以及鼠标指针指向位置对应图片中坐标位置的比例 ;
  • 鼠标指针指向的位置不变 , 指向图片坐标比例不变 , 图片尺寸发生了改变 , 重新计算当前图片的放置位置 , 并设置图片位置 ;

这样图片缩放时 , 始终可以保证鼠标指向的部位保持位置不变 ;

1、保存当前鼠标指针指向的位置

首先 , 在类中定义如下成员字段 ,

  • pointer_x 和 pointer_y 记录的是鼠标指针指向的界面中 Camvas 画布中的坐标位置 ;
  • pointer_ratio_x 和 pointer_ratio_y 记录的是 鼠标指针指向位置对应图片中坐标位置的比例 ;
    public double pointer_ratio_x;public double pointer_ratio_y;public int pointer_x;public int pointer_y;

然后 , 在鼠标缩放之前 , 保存当前的鼠标位置及比例 ;

  • 在鼠标滚轮事件 MouseWheelEvent 中 , 可以直接通过调用 e.getX(), e.getY() 获取到当前 鼠标指针 在 Canvas 画布的坐标 ;
  • 根据该 Canvas 中的坐标 , 以及画布的偏移 , 可以计算出该坐标对应图片中的坐标位置 ;
        // 计算画布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 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 ;}

2、根据鼠标指针指向的位置以及比例重新计算图片位置

在鼠标滚轮缩放完成后 , 再根据鼠标指针指向的位置和比例 , 结合图片缩放后的尺寸 , 重新计算画布偏移的位置 , 以达到鼠标指向的图片元素位置基本保持不变的目的 ;

    /*** 计算新的比例*/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);}

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


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

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

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

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

1、代码示例

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;public class LargeCanvas extends JPanel {// 鼠标按下时的坐标 以及 更新后的坐标private int startX, startY;// 当前的位置偏移private int offsetX = 0, offsetY = 0;// 缩放比例,默认为 1.0private 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() {@Overridepublic 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();}});// 添加鼠标动作监听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 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);}
}

2、执行效果

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

将鼠标指针放在 H 位置 , 缩放 , 发现此时缩放 , 就是以当前鼠标指针为中心进行的缩放 ;

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

  1. 【Java AWT 图形界面编程】LayoutManager 布局管理器 ④ ( GridLayout 网格布局 | GridBagLayout 网格包布局 )

    文章目录 一.GridLayout 网格布局 二.GridLayout 构造函数 三.GridLayout 网格布局代码示例 四.GridBagLayout 网格包布局 一.GridLayout 网格 ...

  2. java windowiconified_Java 图形界面编程

    简单入门 package GUI; import java.awt.*; /** * GUI:Graphical user interface * * CLI:command line user in ...

  3. java 图形化界面编程--awt编程

    二. AWT 编程 2.1 AWT简介 ​ 当 JDK 1.0发布时, Sun 提供了 一套基本的GUI类库,这个GUI类库希望可以在所有平台下都能运行 , 这套基本类库被称为"抽象窗口工具 ...

  4. Java图形界面编程模拟ATM自助取款系统

    本人学习Java时一直想做一个图形界面的程序,所以利用闲暇时间,做了一个Java图形界面编程模拟ATM自助取款系统,界面简洁漂亮,基本功能ATM功能实现. 程序初始时 考号:123456 密码:123 ...

  5. java图形界面多线程_多线程编程、Java I/O系统和Java图形界面编程

    多线程编程: 一个正在运行的程序通常称为一个进程,每一个任务称为一个线程,中能够在一个程序内运行多线程的程序称为多线程程序. 线程与进程的区别:①每个进程都需要操作系统为其分配独立的内存空间: ②而同 ...

  6. Java图形编程实验总结_实验二java图形界面编程2015级.doc

    实验二java图形界面编程2015级.doc 实验二JAVA图形界面编程一.实验目的熟悉JAVA运行环境,编程掌握JAVASWING组件的图形界面编程.二.实验环境微机,软件MYECLIPSE,JDK ...

  7. GUI编程(图形界面编程)上

    GUI编程(图形界面编程)上 定义 图形用户界面是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令.调用文件.启动程序或执行其它一些日常任务.与通过键 ...

  8. Python升级之路( Lv11 ) GUI图形界面编程

    Python系列文章目录 第一章 Python 入门 第二章 Python基本概念 第三章 序列 第四章 控制语句 第五章 函数 第六章 面向对象基础 第七章 面向对象深入 第八章 异常机制 第九章 ...

  9. java swing图形界面开发 java.swing简介

    最近在看YouTube上面的视频的时候,虽然学着做了一点界面和一点可以运行的东西,但是里面用到的库文件我还是不明就里的.所以我打算在制作游戏之前,先花几天的时间大概地研究一下关于java.swing的 ...

最新文章

  1. Gitblit用户没有push权限,但是已经在team里面配置了
  2. android游戏开发框架libgdx的使用(完)—杂谈Libgdx
  3. 【转】排序算法复习(Java实现) (二): 归并排序,堆排序,桶式排序,基数排序...
  4. shiro real的理解,密码匹配等
  5. Eclipse下的项目管理插件介绍
  6. 成功解决“ValueError: Unknown metric function:sensitivity”
  7. 【Drools一】值得打工人学习的规则引擎Drools
  8. 清晰架构的 Go 微服务: 程序容器
  9. python编程 从入门到实践-终于懂了python编程从入门到实践
  10. Cache之组相连映射
  11. 第012讲 盒子模型经典应用
  12. 【图像隐写】基于matlab GUI LSB图像隐写【含Matlab源码 713期】
  13. 服务器2012分辨率不能修改,F1 2012分辨率修改办法
  14. 11款企业网络运维监控软件汇总介绍-行云管家
  15. 搜索引擎优化的九大方法
  16. 微众银行助力普惠金融实现高质量发展
  17. 页面图片 “懒加载”
  18. 《信号完整性分析》的读书笔记和总结
  19. 生物识别技术是什么,生物识别技术的比较介绍
  20. 常用的excel操作小技巧--自己用的,仅供记录

热门文章

  1. uva 138 - Street Numbers(等差数列求和)
  2. 一个Ubuntu下禁用笔记本键盘触摸板的简单脚本
  3. 初识Matlab2012a的神经网络工具箱(1)
  4. 蛇行矩阵(详细题解+注释)
  5. html中隐藏域hidden的作用
  6. [USACO06FEB]Treats for the Cows G/S奶牛零食(区间dp)
  7. HMS生态的华为主题风格太多了
  8. mac2600r_水星MAC2600R路由器登录密码是多少?
  9. 【OneNote】官网下载安装后英文改中文
  10. 训练营一期day15