新手学做网站要学什么知识图文教程,东莞网站网络推广公司,长沙网络营销招聘,英文版网站制作swing 使用Graphic2D 绘制图片#xff0c;要实现对图片进行缩放和自由拖动。 1.以鼠标所在的位置为中心#xff0c;滚轮控制缩放
2.缩放后再支持鼠标拖动。 基本原理#xff1a; 利用scale() 函数。进行缩放。但是要注意的地方是#xff0c;如果是在 public void paintCom…swing 使用Graphic2D 绘制图片要实现对图片进行缩放和自由拖动。 1.以鼠标所在的位置为中心滚轮控制缩放
2.缩放后再支持鼠标拖动。 基本原理 利用scale() 函数。进行缩放。但是要注意的地方是如果是在 public void paintComponent(Graphics g) 里面通过这个Graphics g 参数获取graphic对象进行绘制scale不会影响下一次的绘制。一所以我们可以自行创建一个 “绘图区” 创建一个空的ImageBuffer, 然后获取这个ImageBuffer的 Graphics, 后续全部往这个ImageBuffer的 Graphics 绘制. 二 最后在frame的paintComponent把我们这个 绘图区原样展示出来即可。 即frame的paintComponent只是固定将 绘图区作为一个图片绘制。三甚至可以创建多个ImageBuffer 实现类似于ps多图层的样子各个图层独立paitComponent 汇总显示图层。 自己创建的ImageBuffer的 Graphics 每次scale都是以上一次作为基础累计的缩放。 利用transrate进行移动移动的是坐标系。 每次transrate都是以上一次作为基础累计的平移。 来实现我们的关键代码 作为demo, 代码尽量是一个 main到底 swingDemo.java import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;public class swingDemo {public static void main(String args[]) {new swingDemo();}public static Color BG_COLOR new Color(128, 128, 128);public swingDemo() {JFrame mjf new JFrame(图片查看);ImagePanle mImgeView new ImagePanle();mImgeView.setPreferredSize(new Dimension(500, 500));mImgeView.setMinimumSize(new Dimension(500, 500));mImgeView.setBackground(BG_COLOR);JMenuBar jmb new JMenuBar();JMenu meSetting new JMenu(文件);JMenuItem mOpen new JMenuItem(打开);mOpen.addActionListener(new ActionListener() {Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubBufferedImage curBufferedImg;JFileChooser fileChooser new JFileChooser();fileChooser.setMultiSelectionEnabled(true);fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);fileChooser.setMultiSelectionEnabled(false);int option fileChooser.showOpenDialog(mjf);if (option JFileChooser.APPROVE_OPTION) {try {File file fileChooser.getSelectedFile();curBufferedImg ImageIO.read(new File(file.getAbsolutePath()));mImgeView.updateImage(curBufferedImg);} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}});meSetting.add(mOpen);jmb.add(meSetting);mjf.setJMenuBar(jmb);mjf.add(mImgeView);mjf.setMinimumSize(new Dimension(800, 600));mjf.setVisible(true);mjf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}class ImagePanle extends JPanel {BufferedImage mSrcBuffeImg null;private static final long serialVersionUID 1L;private double mScale 1.0;private static final boolean B_REAL_SIZE true;private double mCurX 0;private double mCurY 0;private double mStartX 0;private double mStartY 0;private double mTranslateX 0;private double mTranslateY 0;// 记录最初原始坐标系用于清除背景AffineTransform mOriginTransform;BufferedImage mViewBufferImg;Graphics2D mViewG2d;void refreshView() {clear_buffer(mViewG2d, mOriginTransform, mViewBufferImg);mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);repaint();}void clear_buffer(Graphics2D g2d, AffineTransform org, BufferedImage bufImg) {
// 将保存的测量数据重新在经过变换后的坐标系上进行绘制// 先恢复一下原始状态保证清空的坐标是全部执行清空然后再切会来AffineTransform temp g2d.getTransform();g2d.setTransform(org);g2d.clearRect(0, 0, bufImg.getWidth(), bufImg.getHeight());g2d.setTransform(temp);}public void updateImage(BufferedImage srcImage) {mSrcBuffeImg srcImage;mViewBufferImg new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);System.out.println(create buff image);mViewG2d mViewBufferImg.createGraphics();mViewG2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);mViewG2d.setBackground(BG_COLOR);System.out.println(crate bufg2d);mOriginTransform mViewG2d.getTransform();refreshView();}private Point internal_getImagePoint(double mouseX, double mouseY) {// 不管是先平移后缩放还是先缩放后平移都以 先减 再缩放的方式可以获取正确double rawTranslateX mViewG2d.getTransform().getTranslateX();double rawTranslateY mViewG2d.getTransform().getTranslateY();// 获取当前的 Scale Transformdouble scaleX mViewG2d.getTransform().getScaleX();double scaleY mViewG2d.getTransform().getScaleY();// 不管是先平移后缩放还是先缩放后平移都以 先减 再缩放的方式可以获取正确int imageX (int) ((mouseX - rawTranslateX) / scaleX);int imageY (int) ((mouseY - rawTranslateY) / scaleY);return new Point(imageX, imageY);}public ImagePanle() {// 启用双缓存setDoubleBuffered(true);this.addMouseWheelListener((MouseWheelListener) new MouseWheelListener() {Overridepublic void mouseWheelMoved(MouseWheelEvent e) {if (mViewG2d null) {return;}mCurX e.getX();mCurY e.getY();int notches e.getWheelRotation();if (notches 0) {// 滚轮向上放大画布mScale 1.1;} else {// 滚轮向下缩小画布mScale 0.9;}Point imagePoint internal_getImagePoint(e.getX(), e.getY());int imageX imagePoint.x;int imageY imagePoint.y;System.out.println(x: e.getX() y: e.getY() ,imagex: imageX x imageY);double tralateX mScale * imageX - imageX;double tralateY mScale * imageY - imageY;mViewG2d.scale(mScale, mScale);mViewG2d.translate(-tralateX / mScale, -tralateY / mScale); // 图片方大就需要把坐标往左移动移动的尺度是要考虑缩放的// 先恢复一下原始状态保证清空的坐标是全部执行清空然后再切会来AffineTransform temp mViewG2d.getTransform();mViewG2d.setTransform(mOriginTransform);mViewG2d.clearRect(0, 0, mViewBufferImg.getWidth(), mViewBufferImg.getHeight());mViewG2d.setTransform(temp);mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);repaint(); // 重新绘制画布}});this.addMouseListener(new MouseListener() {Overridepublic void mouseReleased(MouseEvent e) {// TODO Auto-generated method stubSystem.out.println(mouseReleased: e.getX() x e.getY());}Overridepublic void mousePressed(MouseEvent e) {// TODO Auto-generated method stubSystem.out.println(mousePressed----: e.getX() x e.getY());mStartX e.getX();mStartY e.getY();}Overridepublic void mouseExited(MouseEvent e) {// TODO Auto-generated method stub}Overridepublic void mouseEntered(MouseEvent e) {// TODO Auto-generated method stub}Overridepublic void mouseClicked(MouseEvent e) {// TODO Auto-generated method stubSystem.out.println(mouseClicked----: e.getX() x e.getY());}});this.addMouseMotionListener(new MouseAdapter() {Overridepublic void mouseMoved(MouseEvent e) {// TODO Auto-generated method stub}Overridepublic void mouseDragged(MouseEvent e) {// TODO Auto-generated method stubif (mViewG2d null) {return;}mCurX e.getX();mCurY e.getY();System.out.println(mouseDragged: e.getX() x e.getY() trans: (mCurX - mStartX) : (mCurY - mStartY));// 平移坐标也是相对于变换后的坐标系而言的所以double scaleX mViewG2d.getTransform().getScaleX();double scaleY mViewG2d.getTransform().getScaleY();// TODO mCurX - mStartX 太小比如为2 而scalX 比较大比如为3 则移动的时候回发生 (int)2/3 0; 不移动。// 解决方案把移动 全部在原始坐标系上做也就是最后绘制缓冲区的时候drawimage(transX,transY)mTranslateX (mCurX - mStartX) / scaleX;mTranslateY (mCurY - mStartY) / scaleY;// 自身就是累计的mViewG2d.translate(mTranslateX, mTranslateY);mStartX mCurX;mStartY mCurY;System.out.println(mouseDragged: over);// 先恢复一下原始状态保证清空的坐标是全部执行清空然后再切会来AffineTransform temp mViewG2d.getTransform();mViewG2d.setTransform(mOriginTransform);mViewG2d.clearRect(0, 0, mViewBufferImg.getWidth(), mViewBufferImg.getHeight());mViewG2d.setTransform(temp);mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);repaint();}});}public void reset_scale() {
// 恢复到1.0 缩放0,0 左上角对齐mCurX 0;mCurY 0;mScale 1.0;mViewG2d.setTransform(mOriginTransform);mViewG2d.clearRect(0, 0, mViewBufferImg.getWidth(), mViewBufferImg.getHeight());mViewG2d.drawImage(mSrcBuffeImg, 0, 0, null);repaint(); // 重新绘制画布}Overridepublic void paintComponent(Graphics g) {super.paintComponent(g);if (mViewBufferImg null) {return;}
// 如果有多个“图层”要注意图层的顺序Graphics2D g2d ((Graphics2D) g);g2d.drawImage(mViewBufferImg, 0, 0, null);System.out.println(draw-----------: getWidth() x getHeight());}}}