有没有办法在JLabel上设置锚点?

时间:2017-02-25 13:40:12

标签: java swing jlabel

我希望能够在中心为JLabel设置一个锚点,这样我就可以根据它来移动它。

2 个答案:

答案 0 :(得分:3)

如果您试图将JLabel置于某一点的中心位置,那么您只需要简单的数学就可以做到这一点,仅此而已。

假设您有一个JLabel,或者我们将其命名为" component"的任何组件,它保存在JPanel中,或者我们将调用的任何容器中" container",并假设屏幕上有一个鼠标点 ,比如称为" mousePoint",那么数学很简单:

Point mousePoint = e.getLocationOnScreen();
Point containerLocation = container.getLocationOnScreen();
Dimension componentSize = component.getSize();

int x = mousePoint.x - componentSize.width / 2 - containerLocation.x;
int y = mousePoint.y - componentSize.height / 2 - containerLocation.y;
component.setLocation(x, y);

那就是它。

例如,假设您有两个JLabel,一个带有图像,另一个带有一些文本,那么您可以将相同的MouseListener和MouseMotionListener添加到两者,这将允许您按中心点拖动。以下是我在上述评论中提到的MCVE示例:

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;

public class ClickDragLabel extends JPanel {
    public static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/"
            + "Theodore_Comnenus-Ducas_cropped.jpg/133px-Theodore_Comnenus-Ducas_cropped.jpg";
    private static final int PREF_W = 1000;
    private static final int PREF_H = 850;
    private JLabel imageLabel;
    private JLabel textLabel = new JLabel("Some Random Text");

    public ClickDragLabel(Icon icon) {
        setBackground(Color.WHITE);
        imageLabel = new JLabel(icon);

        setLayout(null);
        imageLabel.setSize(imageLabel.getPreferredSize());
        textLabel.setSize(textLabel.getPreferredSize());

        imageLabel.setLocation(250, 250);
        textLabel.setLocation(10, 10);

        MyMouse myMouse = new MyMouse();
        imageLabel.addMouseListener(myMouse);
        imageLabel.addMouseMotionListener(myMouse);
        textLabel.addMouseListener(myMouse);
        textLabel.addMouseMotionListener(myMouse);

        add(imageLabel);
        add(textLabel);

    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class MyMouse extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
            center(e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            center(e);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            center(e);
        }

        private void center(MouseEvent e) {
            JComponent component = (JComponent) e.getSource();
            Container container = component.getParent();

            Point mousePoint = e.getLocationOnScreen();
            Point containerLocation = container.getLocationOnScreen();
            Dimension componentSize = component.getSize();

            int x = mousePoint.x - componentSize.width / 2 - containerLocation.x;
            int y = mousePoint.y - componentSize.height / 2 - containerLocation.y;
            component.setLocation(x, y);
            container.repaint();
        }

    }

    private static void createAndShowGui() {
        Image img = null;
        try {
            URL imgUrl = new URL(IMG_PATH);
            img = ImageIO.read(imgUrl);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }

        Icon icon = new ImageIcon(img);

        ClickDragLabel mainPanel = new ClickDragLabel(icon);

        JFrame frame = new JFrame("Click-Drag Label");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

发布这个之后,如果我没有提到使用空布局的弊端,那将是我的疏忽。虽然null布局和setBounds()似乎是Swing新手,比如创建复杂GUI的最简单和最好的方法,但是你创建的Swing GUI越多,你在使用它们时会遇到更严重的困难。 。当GUI调整大小时,他们不会调整组件的大小,他们是增强或维护的皇室女巫,当他们放置在滚动窗格中时,他们完全失败,当他们在所有平台或屏幕分辨率不同时看起来很糟糕原来的。我只将它们用于动画,例如上面的动画,而不是别的。

答案 1 :(得分:3)

  

有没有办法在JLabel上设置锚点?

您可以通过将EmptyBorder设置并更改为标签来实现您的目的。

enter image description here enter image description here

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

public class MovableLabel {

    private JComponent ui = null;
    String anchorString = new String(Character.toChars(9875));
    private JLabel label = new JLabel(anchorString);
    int pad = 200;
    SpinnerNumberModel xModel = new SpinnerNumberModel(0, 0, pad, 1);
    SpinnerNumberModel yModel = new SpinnerNumberModel(0, 0, pad, 1);

    MovableLabel() {
        initUI();
    }

    public void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
        Font font = null;
        for (Font f : fonts) {
            if (f.canDisplayUpTo(anchorString) < 0) {
                font = f.deriveFont(40f);
                break;
            }
        }
        label.setFont(font);
        label.setBackground(Color.BLUE);
        setBorder();
        ui.add(label);

        JToolBar tb = new JToolBar();
        ui.add(tb, BorderLayout.PAGE_START);

        ChangeListener changeListener = new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                setBorder();
            }
        };

        tb.add(new JLabel("X"));
        JSpinner xSpinner = new JSpinner(xModel);
        xSpinner.addChangeListener(changeListener);
        tb.add(xSpinner);

        tb.add(new JLabel("Y"));
        JSpinner ySpinner = new JSpinner(yModel);
        ySpinner.addChangeListener(changeListener);
        tb.add(ySpinner);
    }

    private void setBorder() {
        int x = xModel.getNumber().intValue();
        int y = yModel.getNumber().intValue();
        EmptyBorder border = new EmptyBorder(x, y, pad - x, pad - y);
        label.setBorder(border);
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {
                }
                MovableLabel o = new MovableLabel();

                JFrame f = new JFrame(o.getClass().getSimpleName());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}