拖动屏幕周围的jlabel

时间:2011-02-04 00:12:09

标签: java swing jlabel

所以我试图在JFrame周围单击并拖动JLabel。以下代码允许在屏幕上的任何位置按下/拖动鼠标时在屏幕上移动JLabel,但我不知道如何添加第二个ActionListener以检查鼠标是否在标签上单击,假设是解决方案。

我想在屏幕上有多个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);
}
}

4 个答案:

答案 0 :(得分:20)

另一种方法是将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 :(得分:3)

将鼠标侦听器添加到标签而不是面板。 (您可能仍需要在面板上使用鼠标监听器进行拖动,但至少标签上的那个可以告诉您它是否已被选中)。

答案 2 :(得分:3)

受您的代码和user compilex's answer启发,请遵循以下示例:

Screenshot

完整代码:

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

解释被添加为评论。

提示

如果您要在Component dragP上添加Container,而不是&#34;可拖动&#34;,请查看documentation on Container.findComponentAt(int x, int y)。标签。

此外,在这种情况下,您可以使用Container.getComponentAt(int x, int y)。我建议你先阅读他们的(小)文件。

答案 3 :(得分:1)

创建两个全局变量:

int x_pressed = 0;
int y_pressed = 0;

然后创建两个事件(mousePressed和mouseDragged over 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);
    }
});