当前位置: 首页 > 知识库问答 >
问题:

在JLabel中的ImageIcon上添加标记

澹台鸿光
2023-03-14

所以我在想办法修改Java的图像。换句话说,如果用户点击了图像,一个标记将被放在用户刚刚点击的地方。我有一个ImageIcon,放在一个JLabel中。到目前为止,我采用的方法是使用JLayeredPanel将另一个JPanel放在JLabel的顶部,并在这个JPanel上绘制:

//...
ImageIcon icon = new ImageIcon("foo.jpg");
JLabel lb = new JLabel(icon);
JPanel glass = new JPanel();
lb.setBounds(0, 0, 100, 100);
glass.setBounds(0, 0, 100, 100);
glass.setOpaque(false);
LayeredPane container = new LayeredPane();
container.add(lb, 1);
container.add(glass, 2);

//...

但这种方式似乎行不通。我从来没有看到背景图像(以lb为单位的图像)。所以我想知道我是不是走对了路?或者有没有更干净的方法来实现这一点?

共有1个答案

程和煦
2023-03-14

使用jlayeredpane或glass窗格来处理类似的事情并没有什么错,我个人觉得这很麻烦,因为在一个大型应用程序中,您往往希望使用这些层来处理任何数量的事情,所以它变得非常复杂非常快。

我更喜欢把它留在“家里”,可以这么说...

就我个人而言,我会使用自定义组件。这将工作流隔离到一个非常特殊的位置,并使提供您可能喜欢的定制变得更加容易...

public class MarkImage {

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

    public MarkImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private BufferedImage background;
        private List<Point> clickPoints;

        public TestPane() {
            clickPoints = new ArrayList<>(25);
            try {
                background = ImageIO.read(getClass().getResource("/Miho_Small.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    clickPoints.add(e.getPoint());
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g.drawImage(background, x, y, this);
            }
            g.setColor(Color.RED);
            for (Point p : clickPoints) {
                g.fillOval(p.x - 4, p.y - 4, 8, 8);
            }
        }

    }

}

我还会考虑使用jxlayer(在Java 7中也称为jlayer)。这是最好的描述为玻璃窗格的部件(在类固醇)。有关详细信息,请查看如何装饰组件...

这是一个使用Java 7的jlayer的示例。jlayerjxlayer之间有一些细微的区别,但是转换它并不需要太多...

(抱歉,抵挡不住曾经有过的诱惑)

public class MarkLayer {

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

    public MarkLayer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new GridBagLayout());

                    JLabel label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/Miho_Small.png"))));
                    LayerUI<JLabel> layerUI = new MarkLayerUI();
                    JLayer<JLabel> layer = new JLayer<>(label, layerUI);

                    frame.add(layer);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class MarkLayerUI extends LayerUI<JLabel> {

        private Map<JLayer, List<Point>> mapPoints;

        public MarkLayerUI() {
            mapPoints = new WeakHashMap<>(25);
        }

        @Override
        public void installUI(JComponent c) {
            System.out.println("install");
            super.installUI(c);
            JLayer layer = (JLayer) c;
            layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
        }

        @Override
        public void uninstallUI(JComponent c) {
            super.uninstallUI(c);
            mapPoints.remove((JLayer) c);
        }

        @Override
        protected void processMouseEvent(MouseEvent e, JLayer<? extends JLabel> l) {
            if (e.getID() == MouseEvent.MOUSE_CLICKED) {

                List<Point> points = mapPoints.get(l);
                if (points == null) {
                    points = new ArrayList<>(25);
                    mapPoints.put(l, points);
                }
                Point p = e.getPoint();
                p = SwingUtilities.convertPoint(e.getComponent(), p, l);
                points.add(p);
                l.repaint();

            }
        }

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2d = (Graphics2D) g.create();
            super.paint(g2d, c);
            g2d.setColor(Color.BLUE);
            g2d.drawRect(0, 0, c.getWidth() - 1, c.getHeight() - 1);
            List<Point> points = mapPoints.get((JLayer) c);
            if (points != null && points.size() > 0) {
                g2d.setColor(Color.RED);
                for (Point p : points) {
                    g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
                }
            }
            g2d.dispose();
        }
    }
}

蓝色边框作为图层的一部分呈现出来,这给了你一个关于你可以点击哪里的指导--我这样做是为了测试和演示的目的

 类似资料:
  • 问题内容: 首先,这是我使用秋千的第一个星期,如果我的问题太明显,那就对不起。另外,我需要使用标准Java库的解决方案,因为这是用于家庭作业,不允许使用奇怪的库。 我将JLabel与ImageIcon一起使用以在JFrame上显示图像。现在,我想将屏幕上的图像旋转到任意角度。我发现了有关Graphics2D的一些信息,但我找不到实现此目的的方法。 由于我发现的解决方案不起作用或不理解,因此我对旋转

  • 问题内容: 我已经在两个JPanel之间实现了这种非常基本的拖放操作,但这并不能真正满足我的要求! 对不起,我在这里不太清楚。我试图将ImageIcon从imageselect面板上的JLabel拖动到故事情节面板上的另一个JLabel。我可以使用上面的代码来做到这一点。但是,当我这样做时,可以从imageselect面板中拖动一个ImageIcon,然后在同一面板上替换另一个ImageIcon。

  • 问题内容: 我正在制作一个具有以下布局()的Java Swing应用程序: 当用户添加或删除图标时,其他图标应缩小或增长。 我的问题很简单:我有一个包含;如何调整此图标的大小? 问题答案: 调整图标大小并不容易。您需要使用Java的2D图形来缩放图像。第一个参数是Image类,您可以从类中轻松获取。您可以使用class加载图像文件,然后只需调用getter方法即可获取图像。

  • 我在向JFrame添加JLabel时遇到问题。我使用了一些教程中描述的JPanel,但标签不会在框架中弹出;其他swing组件(如JTextField、JButton等)也存在同样的问题。。绘制直线、矩形等确实可行。我希望有人知道,我在这里犯了什么样的错误: 主方法位于另一个类中: 框架按预期弹出,但JLabel丢失。感谢所有有用的评论。

  • 我有一个9x9面板,它是每个面板都有一个JLabel,所以 我试过: 但是,我发现您很可能不能将“UndoableEditListener”添加到JLabels中。(对吗?) 我看到了一些可以将“UndoableEditListener”添加到JTextPane的示例,所以我想也许我可以创建一个JTextPane窗格[9][9],并将一个textpane添加到每个JLabel(添加到JPanel中

  • 问题内容: 是否可以在另一个JLabel上添加一个JLabel?谢谢。 问题答案: 简短的回答是肯定的,一个是一个,所以它可以接受(A 是的子类)添加到使用方法: 在以上代码中,将添加到中。 但是,从视觉上看,显示了带有文本“ Hello”的标签,因此无法真正看到包含在标签中的标签。 因此,问题就来了,一个人到底想通过在另一个标签之上添加一个标签来完成什么工作。 编辑: 从评论: 好吧,我想做的是