2016-11-24 25 views
0

我有两件事我试图做的:突出显示鼠标悬停上的JPanel,并在鼠标拖动时移动蓝色方块。事情是,这需要我将MouseListeners添加到不同的组件。当我这样做时,我只能使用一个功能 - 另一个功能被阻止。我可以做什么以使这两个功能都起作用?如何将多个MouseListeners添加到单个JFrame?

注意:有时JFrame不显示任何东西 - 你只需要继续运行它,直到它(通常需要2-3次尝试)。如果它还有其他奇怪的东西,就继续运行直到它工作。评论> 5次尝试后它是否仍然无法正常工作。

它应该是什么样子:sucessful start screenshot

主要(创建的JFrame,容器,和孩子们,并增加了MouseListeners)

public class Main extends JFrame{ 
    private static final long serialVersionUID = 7163215339973706671L; 
    private static final Dimension containerSize = new Dimension(640, 477); 
    static JLayeredPane layeredPane; 
    static JPanel container; 

    public Main() { 
     super("Multiple MouseListeners Test"); 
     setSize(640, 477); 
     setLocationRelativeTo(null); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setResizable(false); 
     setVisible(true); 

     layeredPane = new JLayeredPane(); 
     layeredPane.setPreferredSize(containerSize); 
     getContentPane().add(layeredPane); 

     createContainer(); 

     layeredPane.add(container, JLayeredPane.DEFAULT_LAYER); 

     createChildren(4, 4); 

     new MovableObject(); 

     MovableObjectMouseListener moml = new MovableObjectMouseListener(); 
     //comment these two out and the highlighter works 
     layeredPane.addMouseListener(moml); 
     layeredPane.addMouseMotionListener(moml); 
    } 

    private void createChildren(int columns, int rows){ 
     for (int i = 0; i < columns; i++){ 
      for (int j = 0; j < rows; j++){ 
       JPanel child = new JPanel(new BorderLayout()); 
       child.setBackground(Color.LIGHT_GRAY); 
       //comment this out and you can move the MovableObject 
       child.addMouseListener(new HighlightJPanelsMouseListener()); 
       container.add(child); 
      } 
     } 
    } 

    private JPanel createContainer(){ 
     container = new JPanel(); 
     container.setLayout(createLayout(4, 4, 1, 1)); 
     container.setPreferredSize(containerSize); 
     container.setBounds(0, 0, containerSize.width, containerSize.height); 
     return container; 
    } 

    private GridLayout createLayout(int rows, int columns, int hGap, int vGap){ 
     GridLayout layout = new GridLayout(rows, columns); 
     layout.setHgap(hGap); 
     layout.setVgap(vGap); 
     return layout; 
    } 

    public static void main(String[] args) { 
     new Main(); 
    } 
} 

HighlightJPanelsMouseListener(创建MouseListeners那将被添加到儿童中)

public class HighlightJPanelsMouseListener implements MouseListener{ 
    private Border grayBorder = BorderFactory.createLineBorder(Color.DARK_GRAY); 

    public HighlightJPanelsMouseListener() { 
    } 

    public void mouseEntered(MouseEvent e) { 
     Component comp = (Component) e.getSource(); 
     JPanel parent = (JPanel) comp; 
     parent.setBorder(grayBorder); 
     parent.revalidate(); 
    } 

    public void mouseExited(MouseEvent e) { 
     Component comp = (Component) e.getSource(); 
     JPanel parent = (JPanel) comp; 
     parent.setBorder(null); 
     parent.revalidate(); 
    } 

    public void mousePressed(MouseEvent e){} 
    public void mouseReleased(MouseEvent e){} 
    public void mouseClicked(MouseEvent e) {} 
} 

MovableObject(创建MovableObject)

download blueSquare.png或使用其他图像。请记住将以下图片的名称更改为您的图片。

public class MovableObject { 
    public MovableObject() { 
     JPanel parent = (JPanel) Main.container.findComponentAt(10, 10); 
     ImageIcon icon = null; 
     //use any image you might have laying around your workspace - or download the one above 
     URL imgURL = MovableObject.class.getResource("/blueSquare.png"); 

     if (imgURL != null){ 
      icon = new ImageIcon(imgURL); 
     }else{ 
      System.err.println("Couldn't find file"); 
     } 

     JLabel movableObject = new JLabel(icon); 
     parent.add(movableObject); 
     parent.revalidate(); 
    } 
} 

MovableObjectMouseListener(则创建的MouseListener用于MovableObject)

public class MovableObjectMouseListener implements MouseListener, MouseMotionListener{ 
    private JLabel replacement; 
    private int xAdjustment, yAdjustment; 

    public void mousePressed(MouseEvent e){ 
     replacement = null; 
     Component c = Main.container.findComponentAt(e.getX(), e.getY()); 

     if (!(c instanceof JLabel)){ 
      return; 
     } 

     Point parentLocation = c.getParent().getLocation(); 
     xAdjustment = parentLocation.x - e.getX(); 
     yAdjustment = parentLocation.y - e.getY(); 
     replacement = (JLabel)c; 
     replacement.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment); 

     Main.layeredPane.add(replacement, JLayeredPane.DRAG_LAYER); 
     Main.layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 
    } 

    public void mouseDragged(MouseEvent me){ 
     if (replacement == null){ 
      return; 
     } 

     int x = me.getX() + xAdjustment; 
     int xMax = Main.layeredPane.getWidth() - replacement.getWidth(); 
     x = Math.min(x, xMax); 
     x = Math.max(x, 0); 

     int y = me.getY() + yAdjustment; 
     int yMax = Main.layeredPane.getHeight() - replacement.getHeight(); 
     y = Math.min(y, yMax); 
     y = Math.max(y, 0); 

     replacement.setLocation(x, y); 
    } 


    public void mouseReleased(MouseEvent e){ 
     Main.layeredPane.setCursor(null); 

     if (replacement == null){ 
      return; 
     } 

     int xMax = Main.layeredPane.getWidth() - replacement.getWidth(); 
     int x = Math.min(e.getX(), xMax); 
     x = Math.max(x, 0); 

     int yMax = Main.layeredPane.getHeight() - replacement.getHeight(); 
     int y = Math.min(e.getY(), yMax); 
     y = Math.max(y, 0); 


     Component c = Main.container.findComponentAt(x, y); 
     Container parent = (Container) c; 
     parent.add(replacement); 
     parent.validate(); 
    } 

    public void mouseClicked(MouseEvent e) {} 
    public void mouseMoved(MouseEvent e) {} 
    public void mouseEntered(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) {} 
} 
+0

'有时JFrame不显示任何东西 - 所有组件都应该添加到框架之前,使框架可见。 – camickr

回答

2

没有看详细的代码,但我会建议你需要拖动的MouseListener添加到可移动物体(即JLabel)而不是面板。然后标签将获得拖动事件,面板将获得mouseEntered/Exited事件。

这会导致当您移过标签(您不想发生这种情况)时现在生成的mouseExited事件出现附加问题。请查看:how to avoid mouseExited to fire while on any nested component以解决此问题。