2011-02-04 18 views
8

Así que estoy tratando de hacer clic y arrastrar un JLabel alrededor de un JFrame. El siguiente código permite mover un JLabel alrededor de la pantalla cuando se presiona/arrastra el mouse en cualquier punto de la pantalla, pero no estoy seguro de cómo agregar un segundo ActionListener para verificar si el mouse hace clic en la etiqueta, suponiendo que es la solución.arrastrando un jlabel alrededor de la pantalla

Me gustaría tener varios JLabels en la pantalla para que la única etiqueta que se mueve sea la que el mouse ha hecho clic y ahora está arrastrando.

Gracias.

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

Por favor, ver además de mi respuesta –

Respuesta

3

Agregue un detector de mouse a la etiqueta en lugar del panel. (Es posible que aún necesite un detector de mouse en el panel para el arrastre, pero al menos el de la etiqueta puede indicarle si fue seleccionado).

19

Otra forma de hacerlo es agregar el JLabel a un JLayeredPane oa un JPanel en un JLayeredPane y agregar un MouseAdapter como MouseListener y MouseMotionListener de JLayeredPane. Luego, cuando haga clic en la etiqueta, muévala al JLayeredPane.DRAG_LAYER de JLayeredPane para que se mueva encima de todo lo demás, luego coloque el JLabel en el nivel más apropiado para el lanzamiento del mouse. He encontrado que esto funciona bien cuando muevo piezas de ajedrez en un tablero de ajedrez, por ejemplo, y desea asegurarse de que la pieza que está moviendo se muestre sobre todas las otras piezas al arrastrarla.

Adición: Probablemente haya dejado este hilo, pero si vuelve, o para el beneficio de otros, quería aclarar a qué me refería al utilizar un JLayeredPane publicando un ejemplo.

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(); 
      } 
     }); 
    } 
} 

No dude en enviar cualquier pregunta, aclaración o correcciones.

+1

Disculpa el tamaño del código. :( –

+3

No es necesario disculparse. Es útil :) –

1

crear dos variables globales:

int x_pressed = 0; 
int y_pressed = 0; 

luego crear dos eventos (mousePressed y mouseDragged sobre 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

Inspirado por su código y user compilex's answer, sigue la demostración:

Screenshot

Código completo:

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); 
    } 
} 

Explicaciones se agregan como comentarios.

Consejos:

echar un vistazo a la documentation on Container.findComponentAt(int x, int y), si se va a añadir Component s en el dragPContainer, excepto las etiquetas "que pueden arrastrarse".

Además, puede utilizar Container.getComponentAt(int x, int y), en este caso. Le sugiero que primero lea su documentación (pequeña).

+0

[_This_] (http://stackoverflow.com/a/4894516/6746785) answer Sin embargo muestra sus etiquetas arrastradas encima de todas las demás. Buen trabajo _Hovercraft Full Of Eels_. – thanopi57