'How to set the focus to an image or a label ?[Java Swing]

Let's say I have several images, each of them in a label, is there a way to set the focus on one of the images or JLabels by clicking at it and do some image processing on the clicked image (blur, black and white...).

Any help is appreciated



Solution 1:[1]

You could...

Use JButtons instead, it's kind of what they are designed for...

enter image description here

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            setLayout(new GridLayout(-1, 3));
            for (int index = 1; index < 13; index++) {
                BufferedImage image = ImageIO.read(getClass().getResource("/images/Cute" + index + ".png"));
                Image scaled = image.getScaledInstance(50, -1, Image.SCALE_SMOOTH);
                JButton btn = new JButton(new ImageIcon(scaled));
                btn.putClientProperty("image", image);
                add(btn);
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JButton btn = (JButton) e.getSource();
                        BufferedImage img = (BufferedImage) btn.getClientProperty("image");
                        // Do stuff
                    }
                });
            }
        }

    }
}

See How to Use Buttons, Check Boxes, and Radio Buttons

Don't want the button "fill" effects?

That becomes a little more complicated, but not impossible...

enter image description here

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.EmptyBorder;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            setLayout(new GridLayout(-1, 3));
            for (int index = 1; index < 13; index++) {
                BufferedImage image = ImageIO.read(getClass().getResource("/images/Cute" + index + ".png"));
                Image scaled = image.getScaledInstance(50, -1, Image.SCALE_SMOOTH);
                JButton btn = new JButton();
                btn.addFocusListener(new FocusListener() {
                    @Override
                    public void focusGained(FocusEvent e) {
                        // Focus.color is for MacOS, Button.focus should work under
                        // most other look and feels
                        btn.setBorder(new RoundBorder());
                    }

                    @Override
                    public void focusLost(FocusEvent e) {
                        btn.setBorder(new EmptyBorder(1, 1, 1, 1));
                    }
                });
                btn.setBorder(new EmptyBorder(1, 1, 1, 1));
                btn.setIcon(new ImageIcon(scaled));
                btn.putClientProperty("image", image);
                add(btn);
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JButton btn = (JButton) e.getSource();
                        BufferedImage img = (BufferedImage) btn.getClientProperty("image");
                        // Do stuff
                    }
                });
            }
        }

        public class RoundBorder extends AbstractBorder {
            @Override
            public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                g2d.setColor(UIManager.getColor("Focus.color"));
                g2d.drawRoundRect(x, y, width - 1, height - 1, 20, 20);
            }
        }

    }
}

Why use buttons?

  1. They are kind built for the purpose; they show focus; they provide feedback when "actioned", which leads into
  2. Free support for keyboard input; you can Tab between the buttons and "action" them with the keyboard - you could even set up keyboard shortcuts without much effort.

but...

You could...

Use a JList, which would allow you to use the arrow keys for navigation

enter image description here

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            setLayout(new BorderLayout());
            DefaultListModel<BufferedImage> model = new DefaultListModel<>();
            for (int index = 1; index < 13; index++) {
                BufferedImage image = ImageIO.read(getClass().getResource("/images/Cute" + index + ".png"));
                model.addElement(image);
            }

            JList list = new JList(model);
            list.setCellRenderer(new BufferedImageListRenderer());
            list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
            list.setVisibleRowCount(4);

            list.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    BufferedImage image = (BufferedImage)list.getSelectedValue();
                    // Do stuff
                }
            });
            list.setSelectedIndex(0);

            add(new JScrollPane(list));
        }

        protected class BufferedImageListRenderer extends DefaultListCellRenderer {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                if (value instanceof BufferedImage) {
                    setText(null);
                    // This is expensive, I'd normally have it cached somewhere
                    Image scaled = ((BufferedImage)value).getScaledInstance(50, -1, Image.SCALE_SMOOTH);
                    setIcon(new ImageIcon(scaled));
                }
                return this;
            }
        }

    }
}

See How to Use Lists

Solution 2:[2]

Or you could...

Just use the JLabels like you actually want to. I'm just going to borrow MadProgrammer's code and replace the buttons with JLabels. I've also added a class member JLabel variable to hold the JLabel object that happened to be clicked upon by the Mouse Pointer. In the demo image below, see how the title bar indicates the image which has current focus. A red border around the image is also a pretty good indicator if you happen to want to do such a thing.

enter image description here

Here is a runnable code:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {
    JFrame frame;
    JLabel labelWithFocus;
    
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    frame = new JFrame();
                    frame.setAlwaysOnTop(true);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public JLabel getLabelWithFocus() {
        return labelWithFocus;
    }

    
    public class TestPane extends JPanel {

        private static final long serialVersionUID = 40666L;

        public TestPane() throws IOException {
            GridLayout layout = new GridLayout(-1, 3);
            layout.setHgap(40);
            layout.setVgap(15);
            setLayout(layout);
            setBackground(Color.WHITE);
            for (int index = 1; index < 13; index++) {
                BufferedImage image = ImageIO.read(getClass().getResource("/images/Cute" + index + ".png"));
                Image scaled = image.getScaledInstance(50, -1, Image.SCALE_SMOOTH);
                JLabel lbl = new JLabel(new ImageIcon(scaled));
                lbl.setName("Cute" + index + ".png");
                lbl.putClientProperty("image", image);
                add(lbl);
                lbl.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        if (labelWithFocus != null ) {
                            labelWithFocus.setBorder(null);
                            // Drop Focus if it currently has focus and is clicked on again.
                            if (lbl.getName().equals(labelWithFocus.getName())) {
                                frame.setTitle("");
                                labelWithFocus = null;
                                return;
                            }
                        }
                        labelWithFocus = (JLabel) e.getSource();
                        BufferedImage img = (BufferedImage) labelWithFocus.getClientProperty("image");
                        lbl.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
                        frame.setTitle(labelWithFocus.getName());
                        
                        // Do anything else you want...
                    }
                    
                    @Override
                    public void mouseEntered(MouseEvent e) {
                        JLabel lbl = (JLabel) e.getSource();
                        lbl.setBorder(BorderFactory.createLineBorder(Color.decode("#2eb8b8"), 1));
                    }
                    
                    @Override
                    public void mouseExited(MouseEvent e) {
                        JLabel lbl = (JLabel) e.getSource();
                         if (lbl == labelWithFocus) {
                            lbl.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
                        }
                        else {
                            lbl.setBorder(null);
                        }
                    }
                });
            }
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2