简体   繁体   English

如何在Java Swing中使用鼠标平移图像

[英]How to pan an image using your mouse in Java Swing

I am creating a Java app that will allow users to view images and to pan the image using their mouse. 我正在创建一个Java应用程序,允许用户使用鼠标查看图像和平移图像。 To implement the panning of the image I use a combination of mouseClicked and mouseDragged events using JViewports. 为了实现图像的平移,我使用mouseDragged结合使用mouseClickedmouseDragged事件。 The bulk of the code is in the mouseDragged method 大部分代码都在mouseDragged方法中

public void mouseDragged(MouseEvent e, WindowWrapper w) {
    final JViewport vp = someFieldViewPort;

    //Getting the point that the mouse is dragged to to
    Point cp = e.getPoint();
    final Point vPoint = vp.getViewPosition();

    //I found the image went off the content to show the white border so I included this 
    // Here pp is a field that I sent when the mouse is clicked in a separate method

    if(vPoint.getX()+pp.x-cp.x>=0 & vPoint.getY()+pp.y-cp.y>=0)
        vPoint.translate(pp.x-cp.x, pp.y-cp.y);
    else if(vPoint.getX()+pp.x-cp.x>=0 & vPoint.getY()+pp.y-cp.y<0)
        vPoint.translate(pp.x-cp.x, (int) -vPoint.getY());
    else if(vPoint.getX()+pp.x-cp.x<0 & vPoint.getY()+pp.y-cp.y>=0)
        vPoint.translate((int) -vPoint.getX(), pp.y-cp.y);

    //finally set the position of the viewport
    vp.setViewPosition(vPoint);
    vp.repaint();
}

While this works I feel that there must be an easier way to do all of this. 虽然这有效,但我觉得必须有一种更简单的方法来完成所有这些工作。 If not all of it, could the code to prevent the viewport going off the image to the surrounding border be replaced? 如果不是全部的话,是否可以替换防止视口从图像到周围边界的代码?

Try using scrollRectToVisible(...) method instead of JViewport#setViewPosition(...) : 尝试使用scrollRectToVisible(...)方法而不是JViewport#setViewPosition(...)

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class HandScrollDemo {
  static class HandScrollListener extends MouseAdapter {
    private final Point pp = new Point();
    @Override public void mouseDragged(MouseEvent e) {
      JViewport vport = (JViewport)e.getSource();
      JComponent label = (JComponent)vport.getView();
      Point cp = e.getPoint();
      Point vp = vport.getViewPosition();
      vp.translate(pp.x-cp.x, pp.y-cp.y);
      label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
      //vport.setViewPosition(vp);
      pp.setLocation(cp);
    }
    @Override public void mousePressed(MouseEvent e) {
      pp.setLocation(e.getPoint());
    }
  }
  public JComponent makeUI() {
    JLabel label = new JLabel(new Icon() {
      TexturePaint TEXTURE = makeCheckerTexture();
      @Override public void paintIcon(Component c, Graphics g, int x, int y) {
        Graphics2D g2 = (Graphics2D)g.create();
        g2.setPaint(TEXTURE);
        g2.fillRect(x,y,c.getWidth(),c.getHeight());
        g2.dispose();
      }
      @Override public int getIconWidth()  { return 2000; }
      @Override public int getIconHeight() { return 2000; }
    });
    label.setBorder(BorderFactory.createLineBorder(Color.RED, 20));
    JScrollPane scroll = new JScrollPane(label);
    JViewport vport = scroll.getViewport();
    MouseAdapter ma = new HandScrollListener();
    vport.addMouseMotionListener(ma);
    vport.addMouseListener(ma);
    return scroll;
  }
  private static TexturePaint makeCheckerTexture() {
    int cs = 20;
    int sz = cs*cs;
    BufferedImage img = new BufferedImage(sz,sz,BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = img.createGraphics();
    g2.setPaint(Color.GRAY);
    for(int i=0; i*cs<sz; i++) { for(int j=0; j*cs<sz; j++) {
      if((i+j)%2==0) { g2.fillRect(i*cs, j*cs, cs, cs); }
    }}
    g2.dispose();
    return new TexturePaint(img, new Rectangle(0,0,sz,sz));
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() { createAndShowGUI(); }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new HandScrollDemo().makeUI());
    f.setSize(320, 320);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

I would do it in a different way. 我会以不同的方式做到这一点。 I would probably define an object called Image or similar. 我可能会定义一个名为Image或类似的对象。 It would define a BufferedImage and two int values: x and y . 它将定义一个BufferedImage和两个int值: xy

The Image object would also have a draw() method that would just know how to draw an image to a Graphics2D object at the x, y location. Image对象还有一个draw()方法,该方法只知道如何在x, y位置将图像绘制到Graphics2D对象。

On mouse events, I would modify the x and y values inside the Image object and under the paint of the component I would call image.draw(g2) . 在鼠标事件上,我会修改Image对象内部的xy值,并在组件的paint下调用image.draw(g2)

+1 to @Dans answer. +1给@Dans回答。

Here is an example I made, basically uses JPanel with added MouseAdapter and overrides mousePressed() and mouseDragged() methods. 这是我做的一个例子,基本上使用JPanel添加了MouseAdapter并覆盖了mousePressed()mouseDragged()方法。 mouseDragged() method will increment x and y co-ordinates of image accordingly and will be drawn via paintComponent(...) of JPanel and Graphics2D#drawImage(Image img,int x,int y,ImageObserver io) . mouseDragged()方法将相应地增加图像的xy坐标,并将通过JPanelGraphics2D#drawImage(Image img,int x,int y,ImageObserver io) paintComponent(...)绘制。

Before click and drag of mouse: 在单击并拖动鼠标之前:

在此输入图像描述

After click and drag of mouse: 点击并拖动鼠标后:

在此输入图像描述

//necessary imports
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    /**
     * Default constructor
     */
    public Test() {
        initComponents();
    }

    /**
     * Initialize GUI and components (including ActionListeners etc)
     */
    private void initComponents() {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        PanPanel pp = null;
        try {
            pp = new PanPanel(ImageIO.read(new URL("http://www.sellcar.co.za/wp-content/uploads/2011/01/Porsche_911_Turbo.jpg")));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        frame.add(pp);
        //pack frame (size JFrame to match preferred sizes of added components and set visible
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        /**
         * Create GUI and components on Event-Dispatch-Thread
         */
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    //set nimbus look and feel
                    for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                        if ("Nimbus".equals(info.getName())) {
                            UIManager.setLookAndFeel(info.getClassName());
                            break;
                        }
                    }
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }
                //create GUI instance
                Test test = new Test();
            }
        });
    }
}

class PanPanel extends JPanel {

    private int x, y;
    private int width = 400, height = 400;
    BufferedImage img;
    private final static RenderingHints textRenderHints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    private final static RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    private final static RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    static int startX, startY;

    public PanPanel(BufferedImage img) {
        x = 0;
        y = 0;
        this.img = img;

        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent me) {
                super.mousePressed(me);
                startX = me.getX();
                startY = me.getY();
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent me) {
                super.mouseDragged(me);

                if (me.getX() < startX) {//moving image to right
                    x -= 2;
                } else if (me.getX() > startX) {//moving image to left
                    x += 2;
                }

                if (me.getY() < startY) {//moving image up
                    y -= 2;
                } else if (me.getY() > startY) {//moving image to down
                    y += 2;
                }
                repaint();
            }
        });
    }

    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);
        Graphics2D g2d = (Graphics2D) grphcs;

        //turn on some nice effects
        applyRenderHints(g2d);

        g2d.drawImage(img, x, y, null);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }

    public static void applyRenderHints(Graphics2D g2d) {
        g2d.setRenderingHints(textRenderHints);
        g2d.setRenderingHints(imageRenderHints);
        g2d.setRenderingHints(renderHints);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM