Java JButton two or more icons

I would like to set two or more icons to one JButton (Java, Swing). Is it possible?

I add picture made in drawing. ;-)

enter image description here

Upvotes: 0

Views: 619

Answers (2)

Andrew Thompson
Andrew Thompson

Reputation: 168825

Are those two icons (happy / sad) literally the icons required? If so, I'd suggest instead using a JCheckBox and setting the icons as the default and selected icon (so the check box changes between them on selection).

Here's how (using a red icon for happy, and blue icon for sad).

import java.awt.*;
import java.io.IOException;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.*;
import javax.imageio.ImageIO;

public class CheckBoxWithIcons {

    private JComponent ui = null;
    Image happyImage;
    Image sadImage;

    CheckBoxWithIcons() {
        try {
            initUI();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public final void initUI() throws MalformedURLException, IOException {
        if (ui!=null) return;

        happyImage = ImageIO.read(new URL("https://i.sstatic.net/wCF8S.png"));
        sadImage = ImageIO.read(new URL("https://i.sstatic.net/gJmeJ.png"));

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

        JCheckBox checkBox = new JCheckBox("Mood", true);
        checkBox.setIcon(new ImageIcon(sadImage));
        checkBox.setSelectedIcon(new ImageIcon(happyImage));
        ui.add(checkBox);
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception useDefault) {
            }
            CheckBoxWithIcons o = new CheckBoxWithIcons();

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

Upvotes: 1

weisj
weisj

Reputation: 962

The best way to achieve this is by creating a custom class that implements the Icon interface, which simply paints two given icons side by side.

public class TwoIcon implements Icon {

    private final int iconGap = 2;
    private final Icon icon1;
    private final Icon icon2;

    public TwoIcon(final Icon icon1, final Icon icon2) {
        this.icon1 = icon1;
        this.icon2 = icon2;
    }

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
        int mid = getIconHeight() / 2;
        int y1 = y + mid - icon1.getIconHeight() / 2;
        int y2 = y + mid - icon2.getIconHeight() / 2;
        icon1.paintIcon(c, g, x, y1);
        icon2.paintIcon(c, g, x + icon1.getIconWidth() + iconGap, y2);
    }

    @Override
    public int getIconWidth() {
        return icon1.getIconWidth() + icon2.getIconWidth() + iconGap;
    }

    @Override
    public int getIconHeight() {
        return Math.max(icon1.getIconHeight(), icon2.getIconHeight());
    }
}

The icons will be painted side by side with a padding of 2 and centered vertically. Play around with the spacing if you want them to be aligned differently.

Icon leftIcon = ...
Icon rightIcon = ...
button.setIcon(new TwoIcon(leftIcon, rightIcon));

Result: I am simply using Icons that paint a solid colour here. One is 16x16 and the other 20x20 in size to demonstrate the vertical alignment.

enter image description here

In fact this is not restricted to JButton and will for any JComponent that can use an icon e.g. JLabel etc.

Upvotes: 7

Related Questions