[英]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
结合使用mouseClicked
和mouseDragged
事件。 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
值: x
和y
。
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
对象内部的x
和y
值,并在组件的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()
方法将相应地增加图像的x
和y
坐标,并将通过JPanel
和Graphics2D#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.