2

I have created some focusable JLabels and would like to visually indicate when one of them has focus keeping it consistent with current look and feel.

The closest thing to this that come to mind are JCheckBox and JButton focus indicators, but I cannot find where those are defined. I would have expected them to be borders accessible through LAF defaults, but this doesn't seem to be the case. This answer by camickr mentions that those are not even borders. So what are they? Are they painted in a completely implementation dependent way?

How can I mimic the focus indicator of a JCheckBox or a JButton for a JLabel on different platforms? I'm currently using label.setBorder(UIManager.getBorder("List.focusCellHighlightBorder")) but that only looks okay on some LAFs.

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

public class JButtonFocusBorder extends JFrame {

    private JPanel panel;
    private JTextField textfield1;
    private JLabel label1;
    private JTextField textfield2;
    private JLabel label2;
    private JCheckBox checkbox1;
    private JButton button;

    public JButtonFocusBorder() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        initComponents();

        label1.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        label2.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

        label1.setFocusable(true);
        label2.setFocusable(true);

        FocusListener focusListener = new FocusAdapter() {

            @Override
            public void focusGained(FocusEvent e) {
                JLabel label = (JLabel) e.getSource();
                // looking for a replacement of this
                label.setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
            }

            @Override
            public void focusLost(FocusEvent e) {
                JLabel label = (JLabel) e.getSource();
                label.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
            }
        };
        label1.addFocusListener(focusListener);
        label2.addFocusListener(focusListener);

        MouseListener mouseListener = new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                JLabel label = (JLabel) e.getSource();
                label.requestFocusInWindow();
            }

        };
        label1.addMouseListener(mouseListener);
        label2.addMouseListener(mouseListener);

        pack();
        setResizable(false);
        setLocationRelativeTo(null);
    }

    private void initComponents() {
        panel = new JPanel(new GridBagLayout());
        add(panel);

        GridBagConstraints gbc;

        label1 = new JLabel("Field1:");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        panel.add(label1, gbc);        

        textfield1 = new JTextField(20);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        panel.add(textfield1, gbc);

        label2 = new JLabel("Field2:");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        panel.add(label2, gbc);        

        textfield2 = new JTextField(20);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 1;
        panel.add(textfield2, gbc);

        checkbox1 = new JCheckBox("CheckBox1");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 2;
        panel.add(checkbox1, gbc);

        button = new JButton("Apply");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 3;
        panel.add(button, gbc);
    }

    public static void main(String[] args) throws 
            ClassNotFoundException, UnsupportedLookAndFeelException, 
            InstantiationException, IllegalAccessException {
        UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());


        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new JButtonFocusBorder().setVisible(true);
            }
        });
    }

}

P.S.: This question is related to an answer of one of my existing questions and explains why I'd want focusable labels.

Community
  • 1
  • 1
predi
  • 5,528
  • 32
  • 60
  • and by using Nimbus L&F content jumping on the screen (focus enlarge the JLables bound, that unforntatelly are accepted, repainted by LayoutManager), you have to use EmptyBorders to avoids of those funny repainting artefacts – mKorbel Oct 14 '15 at 09:12
  • @mKorbel, that's because on Nimbus `List.focusCellHighlightBorder` border probably isn't the same size as the `EmptyBorders` I'm (already) creating in the example. Like I said, only works on some LAFs. – predi Oct 14 '15 at 09:16
  • 1. border probably isn't the same size as the EmptyBorders ?= Insets, 2. label, description for JCheckBox hasn't any border, 3. for JButtonComponents to use events from ButtonModel (or the same events are implemented in JButtons/AbstractButton APIs and correctly) – mKorbel Oct 14 '15 at 10:26
  • It might be easier to use a JButton – laune Oct 14 '15 at 10:38

0 Answers0