2011-02-04 166 views
8

所以我想單擊並拖動一個JLabel在JFrame周圍。下面的代碼允許JLabel在屏幕上的任意點按下/拖動鼠標時在屏幕上移動,但我不確定如何添加第二個ActionListener來檢查鼠標是否點擊標籤,假設是解決方案。在屏幕上拖動一個jlabel

我想在屏幕上有多個JLabel,以便唯一移動的標籤是鼠標點擊並拖動的標籤。

謝謝。

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class test extends JFrame implements MouseMotionListener { 

private JPanel panel = new JPanel(null);  
private JLabel dragLabel = new JLabel("drag test"); 
private int mouseX = 200; 
private int mouseY = 200; 

public test() { 
    this.add(panel); 
    panel.setBackground(Color.WHITE); 
    panel.add(dragLabel); 
    dragLabel.setForeground(Color.RED); 
    dragLabel.setBounds(mouseX, mouseY, 100, 50); 
    panel.addMouseMotionListener(this); 
} 

@Override 
public void mouseDragged(MouseEvent e) { 
    mouseX = e.getX(); 
    mouseY = e.getY(); 
    dragLabel.setBounds(mouseX, mouseY, 100, 50); 
} 

@Override 
public void mouseMoved(MouseEvent e) {} 

public static void main(String[] args) { 
    test frame = new test(); 
    frame.setVisible(true); 
    frame.setSize(600, 400); 
    frame.setResizable(false); 
    frame.setLocationRelativeTo(null); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
} 
} 
+0

請參閱我的回答除了 – 2011-02-05 16:04:56

回答

3

將鼠標監聽器添加到標籤而不是面板。 (您可能仍然需要在面板上使用鼠標偵聽器進行拖動,但至少標籤上的可以告訴您它是否被選中)。

19

另一種方法是將JLabel添加到JLayeredPane或JLayeredPane擁有的JPanel中,並將MouseAdapter添加爲JLayeredPane的MouseListener和MouseMotionListener。然後,當點擊標籤時,將其移至JLayeredPane的JLayeredPane.DRAG_LAYER,以便移動至其他位置,然後將JLabel放在鼠標釋放時最合適的級別上。例如,在棋盤上移動棋子時,我發現這種方法可以很好地工作,並且您要確保在移動時您移動的棋子顯示在所有其他棋子之上。

此外:您可能已離開此主題,但如果您回來或爲了其他人的利益,我想通過發佈示例來闡明使用JLayeredPane意味着什麼。

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class DragLabelOnLayeredPane extends JLayeredPane { 
    public static final int WIDTH = 680; 
    public static final int HEIGHT = 480; 
    private static final int GRID_ROWS = 8; 
    private static final int GRID_COLS = 6; 
    private static final int GAP = 3; 
    private static final Dimension LAYERED_PANE_SIZE = new Dimension(WIDTH, HEIGHT); 
    private static final Dimension LABEL_SIZE = new Dimension(60, 40); 
    private GridLayout gridlayout = new GridLayout(GRID_ROWS, GRID_COLS, GAP, GAP); 
    private JPanel backingPanel = new JPanel(gridlayout); 
    private JPanel[][] panelGrid = new JPanel[GRID_ROWS][GRID_COLS]; 
    private JLabel redLabel = new JLabel("Red", SwingConstants.CENTER); 
    private JLabel blueLabel = new JLabel("Blue", SwingConstants.CENTER); 

    public DragLabelOnLayeredPane() { 
     backingPanel.setSize(LAYERED_PANE_SIZE); 
     backingPanel.setLocation(2 * GAP, 2 * GAP); 
     backingPanel.setBackground(Color.black); 
     for (int row = 0; row < GRID_ROWS; row++) { 
      for (int col = 0; col < GRID_COLS; col++) { 
       panelGrid[row][col] = new JPanel(new GridBagLayout()); 
       backingPanel.add(panelGrid[row][col]); 
      } 
     } 

     redLabel.setOpaque(true); 
     redLabel.setBackground(Color.red.brighter().brighter()); 
     redLabel.setPreferredSize(LABEL_SIZE); 
     panelGrid[4][3].add(redLabel); 

     blueLabel.setOpaque(true); 
     blueLabel.setBackground(Color.blue.brighter().brighter()); 
     blueLabel.setPreferredSize(LABEL_SIZE); 
     panelGrid[1][1].add(blueLabel); 

     backingPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); 
     setPreferredSize(LAYERED_PANE_SIZE); 
     add(backingPanel, JLayeredPane.DEFAULT_LAYER); 
     MyMouseAdapter myMouseAdapter = new MyMouseAdapter(); 
     addMouseListener(myMouseAdapter); 
     addMouseMotionListener(myMouseAdapter); 
    } 

    private class MyMouseAdapter extends MouseAdapter { 
     private JLabel dragLabel = null; 
     private int dragLabelWidthDiv2; 
     private int dragLabelHeightDiv2; 
     private JPanel clickedPanel = null; 

     @Override 
     public void mousePressed(MouseEvent me) { 
      clickedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint()); 
      Component[] components = clickedPanel.getComponents(); 
      if (components.length == 0) { 
       return; 
      } 
      // if we click on jpanel that holds a jlabel 
      if (components[0] instanceof JLabel) { 

       // remove label from panel 
       dragLabel = (JLabel) components[0]; 
       clickedPanel.remove(dragLabel); 
       clickedPanel.revalidate(); 
       clickedPanel.repaint(); 

       dragLabelWidthDiv2 = dragLabel.getWidth()/2; 
       dragLabelHeightDiv2 = dragLabel.getHeight()/2; 

       int x = me.getPoint().x - dragLabelWidthDiv2; 
       int y = me.getPoint().y - dragLabelHeightDiv2; 
       dragLabel.setLocation(x, y); 
       add(dragLabel, JLayeredPane.DRAG_LAYER); 
       repaint(); 
      } 
     } 

     @Override 
     public void mouseDragged(MouseEvent me) { 
      if (dragLabel == null) { 
       return; 
      } 
      int x = me.getPoint().x - dragLabelWidthDiv2; 
      int y = me.getPoint().y - dragLabelHeightDiv2; 
      dragLabel.setLocation(x, y); 
      repaint(); 
     } 

     @Override 
     public void mouseReleased(MouseEvent me) { 
      if (dragLabel == null) { 
       return; 
      } 
      remove(dragLabel); // remove dragLabel for drag layer of JLayeredPane 
      JPanel droppedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint()); 
      if (droppedPanel == null) { 
       // if off the grid, return label to home 
       clickedPanel.add(dragLabel); 
       clickedPanel.revalidate(); 
      } else { 
       int r = -1; 
       int c = -1; 
       searchPanelGrid: for (int row = 0; row < panelGrid.length; row++) { 
        for (int col = 0; col < panelGrid[row].length; col++) { 
         if (panelGrid[row][col] == droppedPanel) { 
          r = row; 
          c = col; 
          break searchPanelGrid; 
         } 
        } 
       } 

       if (r == -1 || c == -1) { 
        // if off the grid, return label to home 
        clickedPanel.add(dragLabel); 
        clickedPanel.revalidate(); 
       } else { 
        droppedPanel.add(dragLabel); 
        droppedPanel.revalidate(); 
       } 
      } 

      repaint(); 
      dragLabel = null; 
     } 
    } 

    private static void createAndShowUI() { 
     JFrame frame = new JFrame("DragLabelOnLayeredPane"); 
     frame.getContentPane().add(new DragLabelOnLayeredPane()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 
} 

請隨時張貼任何問題,需要澄清或更正。

+1

對不起,我還不知道這個代碼的大小。 :( – 2011-02-05 16:05:40

+3

不需要抱歉,這很有用:) – 2012-09-03 01:01:26

1

創建兩個全局變量:

int x_pressed = 0; 
int y_pressed = 0; 

再創建兩個事件(的mousePressed和的mouseDragged過的JLabel):

lbl_banner.addMouseListener(new MouseAdapter() 
{ 
    @Override 
    public void mousePressed(MouseEvent e) { 
     //catching the current values for x,y coordinates on screen 
     x_pressed = e.getX(); 
     y_pressed = e.getY(); 
    } 
}); 

lbl_banner.addMouseMotionListener(new MouseMotionAdapter(){ 
    @Override 
    public void mouseDragged(MouseEvent e){ 
     //and when the Jlabel is dragged 
     setLocation(e.getXOnScreen() - x_pressed, e.getYOnScreen() - y_pressed); 
    } 
}); 
2

您的代碼和user compilex's answer啓發,如下演示:

Screenshot

Full code:

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.Random; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.border.LineBorder; 

/** 
* A demonstration of moving around labels in a panel. 
* <p> 
* Some labels show up layed out in a grid. Then the 
* user can drag any label anywhere on the panel. 
* </p> 
*/ 
public class LabelDragger { 
    public static void main(final String[] args) { 
     final int labelRows = 5, //How many rows of labels. 
        labelColumns = 5, //How many columns of labels. 
        labelWidth = 55, //Width for each label. 
        labelHeight = 20; //Height for each label. 

     //Border colors for labels: 
     final Color[] colors = new Color[]{Color.BLUE, Color.GREEN, Color.BLACK, Color.GRAY}; 
     final Random prng = new Random(); //For selecting border color for each label. 

     final JPanel dragP = new JPanel(null); //Nicely set to null! :D Did not know that trick. 

     //Creating the listener for the panel: 
     final MouseAdapter ma = new MouseAdapter() { 
      private JLabel selectedLabel = null; //Clicked label. 
      private Point selectedLabelLocation = null; //Location of label in panel when it was clicked. 
      private Point panelClickPoint = null; //Panel's click point. 

      //Selection of label occurs upon pressing on the panel: 
      @Override 
      public void mousePressed(final MouseEvent e) { 

       //Find which label is at the press point: 
       final Component pressedComp = dragP.findComponentAt(e.getX(), e.getY()); 

       //If a label is pressed, store it as selected: 
       if (pressedComp != null && pressedComp instanceof JLabel) { 
        selectedLabel = (JLabel) pressedComp; 
        selectedLabelLocation = selectedLabel.getLocation(); 
        panelClickPoint = e.getPoint(); 
        //Added the following 2 lines in order to make selectedLabel 
        //paint over all others while it is pressed and dragged: 
        dragP.setComponentZOrder(selectedLabel, 0); 
        selectedLabel.repaint(); 
       } 
       else { 
        selectedLabel = null; 
        selectedLabelLocation = null; 
        panelClickPoint = null; 
       } 
      } 

      //Moving of selected label occurs upon dragging in the panel: 
      @Override 
      public void mouseDragged(final MouseEvent e) { 
       if (selectedLabel != null 
         && selectedLabelLocation != null 
         && panelClickPoint != null) { 

        final Point newPanelClickPoint = e.getPoint(); 

        //The new location is the press-location plus the length of the drag for each axis: 
        final int newX = selectedLabelLocation.x + (newPanelClickPoint.x - panelClickPoint.x), 
           newY = selectedLabelLocation.y + (newPanelClickPoint.y - panelClickPoint.y); 

        selectedLabel.setLocation(newX, newY); 
       } 
      } 
     }; 
     dragP.addMouseMotionListener(ma); //For mouseDragged(). 
     dragP.addMouseListener(ma); //For mousePressed(). 

     //Filling the panel with labels: 
     for (int row = 0; row < labelRows; ++row) 
      for (int col = 0; col < labelColumns; ++col) { 

       //Create label for (row, col): 
       final JLabel lbl = new JLabel("Label" + (row * labelColumns + col)); 
       lbl.setHorizontalAlignment(JLabel.CENTER); 
       //lbl.setVerticalAlignment(JLabel.CENTER); 
       lbl.setBounds(col * labelWidth, row * labelHeight, labelWidth, labelHeight); //Grid-like positioning. 
       lbl.setBorder(new LineBorder(colors[prng.nextInt(colors.length)], 2)); //Set a border for clarity. 

       //Add label to panel: 
       dragP.add(lbl); 
      } 

     //Creating and showing the main frame: 
     final JFrame frame = new JFrame(LabelDragger.class.getSimpleName()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     //The size of the content pane adds some extra room for moving the labels: 
     final Dimension paneSize = new Dimension((int)(1.5 * labelWidth * labelColumns), 
               (int)(1.5 * labelHeight * labelRows)); 
     frame.getContentPane().setPreferredSize(paneSize); 
     frame.getContentPane().add(dragP); 

     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 

解釋被添加爲註釋。

提示

documentation on Container.findComponentAt(int x, int y)看看,如果你要在dragPContainer添加Component S,除了 「拖拽」 標籤。

另外,在這種情況下,您可以改爲使用Container.getComponentAt(int x, int y)。我建議你先閱讀他們的(小)文檔。