使用鼠标单击在JLabel内拖动和移动图片

我在JLabel里面有一个图像。

JLabel label = new JLabel(new ImageIcon("C:\\image.jpg")); label.setSize(300,300); 

我想要以下function。

– 我点击JLabel内的一个位置(在图像上)。

– 按下鼠标按钮,我可以在JLabel中更改图像的位置。 (我将图片拖到JLabel内的不同位置)

嗯,这意味着在许多情况下,图片将被裁剪并且在视图之外。

请告诉我如何实现此function?

要添加到JLabel的正确事件侦听器是什么?

这是一个基本的例子……

它的工作原理是将标签划分为3×3网格,其中每个单元格代表图标的可能位置。

 public class TestMouseDrag { public static void main(String[] args) { new TestMouseDrag(); } public TestMouseDrag() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new DragMyIcon()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } protected class DragMyIcon extends JPanel { private JLabel label; public DragMyIcon() { ImageIcon icon = null; try { icon = new ImageIcon(ImageIO.read(getClass().getResource("/bomb.png"))); } catch (IOException ex) { ex.printStackTrace(); } label = new JLabel(icon); label.setHorizontalAlignment(JLabel.CENTER); label.setVerticalAlignment(JLabel.CENTER); setLayout(new BorderLayout()); add(label); MouseHandler handler = new MouseHandler(); label.addMouseListener(handler); label.addMouseMotionListener(handler); } } protected class MouseHandler extends MouseAdapter { private boolean active = false; @Override public void mousePressed(MouseEvent e) { JLabel label = (JLabel) e.getComponent(); Point point = e.getPoint(); active = getIconCell(label).contains(point); if (active) { label.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); } else { label.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } @Override public void mouseReleased(MouseEvent e) { active = false; JLabel label = (JLabel) e.getComponent(); label.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } @Override public void mouseDragged(MouseEvent e) { if (active) { JLabel label = (JLabel) e.getComponent(); Point point = e.getPoint(); int verticalAlign = label.getVerticalAlignment(); int horizontalAlign = label.getHorizontalAlignment(); if (isWithInColumn(label, point, 0)) { horizontalAlign = JLabel.LEFT; } else if (isWithInColumn(label, point, 1)) { horizontalAlign = JLabel.CENTER; } else if (isWithInColumn(label, point, 2)) { horizontalAlign = JLabel.RIGHT; } if (isWithInRow(label, point, 0)) { verticalAlign = JLabel.TOP; } else if (isWithInRow(label, point, 1)) { verticalAlign = JLabel.CENTER; } else if (isWithInRow(label, point, 2)) { verticalAlign = JLabel.BOTTOM; } label.setVerticalAlignment(verticalAlign); label.setHorizontalAlignment(horizontalAlign); label.invalidate(); label.repaint(); } } @Override public void mouseMoved(MouseEvent e) { } protected boolean isWithInColumn(JLabel label, Point p, int gridx) { int cellWidth = label.getWidth() / 3; int cellHeight = label.getHeight(); Rectangle bounds = new Rectangle(gridx * cellWidth, 0, cellWidth, cellHeight); return bounds.contains(p); } protected boolean isWithInRow(JLabel label, Point p, int gridY) { int cellWidth = label.getWidth(); int cellHeight = label.getHeight() / 3; Rectangle bounds = new Rectangle(0, cellHeight * gridY, cellWidth, cellHeight); return bounds.contains(p); } private Rectangle getIconCell(JLabel label) { Rectangle bounds = new Rectangle(); int cellWidth = label.getWidth() / 3; int cellHeight = label.getHeight() / 3; bounds.width = cellWidth; bounds.height = cellHeight; if (label.getHorizontalAlignment() == JLabel.LEFT) { bounds.x = 0; } else if (label.getHorizontalAlignment() == JLabel.CENTER) { bounds.x = cellWidth; } else if (label.getHorizontalAlignment() == JLabel.RIGHT) { bounds.x = cellWidth * 2; } else { bounds.x = 0; bounds.width = 0; } //if (label.getHorizontalAlignment() == JLabel.TOP) { // bounds.y = 0; //} else if (label.getHorizontalAlignment() == JLabel.CENTER) { // bounds.y = cellHeight; //} else if (label.getHorizontalAlignment() == JLabel.BOTTOM) { // bounds.y = cellHeight * 2; //} else { // bounds.y = 0; // bounds.height = 0; //} if (label.getVerticalAlignment() == JLabel.TOP) { bounds.y = 0; } else if (label.getVerticalAlignment() == JLabel.CENTER) { bounds.y = cellHeight; } else if (label.getVerticalAlignment() == JLabel.BOTTOM) { bounds.y = cellHeight * 2; } else { bounds.y = 0; bounds.height = 0; } return bounds; } } } 

从反馈中更新

这个例子基本上使用JLayerdPane来允许在它的容器中重新定位JLabels

 public class MoveMe { public static void main(String[] args) { new MoveMe(); } public MoveMe() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new MoveMePane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class MoveMePane extends JLayeredPane { public MoveMePane() { int width = 400; int height = 400; for (int index = 0; index < 10; index++) { String text = "Label " + index; JLabel label = new JLabel(text); label.setSize(label.getPreferredSize()); int x = (int) Math.round(Math.random() * width); int y = (int) Math.round(Math.random() * height); if (x + label.getWidth() > width) { x = width - label.getWidth(); } if (y + label.getHeight() > width) { y = width - label.getHeight(); } label.setLocation(x, y); add(label); } MoveMeMouseHandler handler = new MoveMeMouseHandler(); addMouseListener(handler); addMouseMotionListener(handler); } @Override public Dimension getPreferredSize() { return new Dimension(400, 400); } } public class MoveMeMouseHandler extends MouseAdapter { private int xOffset; private int yOffset; private JLabel draggy; private String oldText; @Override public void mouseReleased(MouseEvent me) { if (draggy != null) { draggy.setText(oldText); draggy.setSize(draggy.getPreferredSize()); draggy = null; } } public void mousePressed(MouseEvent me) { JComponent comp = (JComponent) me.getComponent(); Component child = comp.findComponentAt(me.getPoint()); if (child instanceof JLabel) { xOffset = me.getX() - child.getX(); yOffset = me.getY() - child.getY(); draggy = (JLabel) child; oldText = draggy.getText(); draggy.setText("What a drag"); draggy.setSize(draggy.getPreferredSize()); } } public void mouseDragged(MouseEvent me) { if (draggy != null) { draggy.setLocation(me.getX() - xOffset, me.getY() - yOffset); } } } } 

首先,我建议使用布局而不是setLayout(null)和setBounds()。 其次,从JLabel中分离ImageIcon。 最后,将JLabel和ImageIcon设置为字段而不是局部变量。

您需要添加MouseListener和MouseMotionListener。

 label.addMouseMotionListener(new MouseAdapter() { public void mouseMoved(MouseEvent arg0) { if(clicked) { label.x++ label.y++ label.repaint(); } } }); label.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent arg0) { clicked = !clicked; } }); 

(抱歉预先罗嗦)

这会导致标签的图像出现在标签所在的位置,当您将鼠标hover在标签上时,它将向东南方向移动。 我创建了一个新的标签类,我在其中覆盖paintComponent并在其中添加了一个绘图图标图标方法,其中x和y是变量。 想法是计算标签上的中心点,然后向西移动该点(x–)向西移动图像的x位置,向南移动(y–),等等。 这只会在标签内移动您的图像。 如果你的鼠标在标签之外,移动就会停止。 如果图像的某些部分位于标签之外,则不会显示该部分。 我会覆盖你的标签类中的paint compoent并将图像移过,然后为每个动作设置图标。

 public class Label1 extends JLabel { public int x; public int y; ImageIcon imageIcon = new ImageIcon("path"); public void paintComponent(Graphics g) { super.paintComponent(g); //No setLocation(x, y) method exists for an image icon or an image. You are on your own on this imageIcon.setLocation(x, y); label.setIcon(imageIcon); } } 

此修改示例基于MadProgrammer的代码。

它显示了我在原帖中描述的行为。 谢谢大家的宝贵帮助,特别是MadProgrammer和Coupon22。 试试看。

 import java.awt.*; import javax.swing.*; import java.awt.event.MouseEvent; import java.awt.event.MouseAdapter; public class TestMouseDrag { public static void main(String[] args) { new TestMouseDrag(); } public TestMouseDrag() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new DragMyIcon("C://image.jpg")); frame.pack(); frame.setSize(500,500); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } protected class DragMyIcon extends JPanel { public static final long serialVersionUID = 172L; private JLabel label; public DragMyIcon(String path) { setLayout(null); ImageIcon icon = null; icon = new ImageIcon(path); label = new JLabel(icon); label.setBounds(0,0,icon.getIconWidth(), icon.getIconHeight()); setBounds(0,0,icon.getIconWidth(), icon.getIconHeight()); label.setHorizontalAlignment(JLabel.CENTER); label.setVerticalAlignment(JLabel.CENTER); add(label); MouseHandler handler = new MouseHandler(); label.addMouseListener(handler); label.addMouseMotionListener(handler); } } protected class MouseHandler extends MouseAdapter { private boolean active = false; private int xDisp; private int yDisp; @Override public void mousePressed(MouseEvent e) { active = true; JLabel label = (JLabel) e.getComponent(); xDisp = e.getPoint().x - label.getLocation().x; yDisp = e.getPoint().y - label.getLocation().y; label.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); } @Override public void mouseReleased(MouseEvent e) { active = false; JLabel label = (JLabel) e.getComponent(); label.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } @Override public void mouseDragged(MouseEvent e) { if (active) { JLabel label = (JLabel) e.getComponent(); Point point = e.getPoint(); label.setLocation(point.x - xDisp, point.y - yDisp); label.invalidate(); label.repaint(); } } @Override public void mouseMoved(MouseEvent e) { } } 

}