putting marks on ImageIcon in JLabel

前端 未结 2 1128
有刺的猬
有刺的猬 2020-12-12 02:15

So I\'m trying to find a way to modify an image in Java. In other words, if user clicks on the image, a mark will be put at the point where the user just clicked. I have an

相关标签:
2条回答
  • 2020-12-12 02:48

    You're on the right track with wanting to use another pane. In Java, there actually already is a glass pane that is designed for just this purpose. Read through this tutorial http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html and it should help you understand.

    0 讨论(0)
  • 2020-12-12 03:03

    There's nothing wrong with using a JLayeredPane or the glass pane for something like this, personally, I find it troublesome, because in a large application, you tend to want to use these layers for any number of things, so it becomes very complicated very fast.

    I prefer to keep it "in the family" so to speak...

    Personally, I would use a custom component. This isolates the work flow to a very particular location and makes it easier to provide the customisations that you might like...

    enter image description here

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

    I'd also consider using JXLayer (AKA JLayer in Java 7). This is best described as a glass pane for components (on steroids). Check out How to decorate components for more details...

    Updated with JLayer Example

    This is an example using Java 7's JLayer. There are some slight differences between JLayer and JXLayer, but it wouldn't take much to convert it...

    (Sorry, couldn't resist the temptation of having ago)

    enter image description here

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

    The blue border is renderer as part of the layer, this gives you a guide as to where you can click - I did this for testing and demonstration purposes

    0 讨论(0)
提交回复
热议问题