13

Is there a standard implementation or library that provides a GUI toggle switch in Swing? I know Swing provides a toggle button, but the UX leaves a bit to be desired. I'm looking for this:

enter image description here

Also, is there a canonical term for this type of control? The Apple HIG refer to it as a UISwitch. I also tried searching for "toggle switch", but I didn't have much luck. (Plenty of JavaScript results, but nothing native.)

mKorbel
  • 109,525
  • 20
  • 134
  • 319
cbednarski
  • 11,718
  • 4
  • 26
  • 33
  • Related examples may be found [here](http://stackoverflow.com/a/5528653/230513) and [here](http://stackoverflow.com/a/6036048/230513). – trashgod Feb 05 '12 at 04:11

4 Answers4

11

You might mimic it by using two icons to represent on & off, then set those to a JToggleButton.

As an aside, users want to see logical and consistent GUIs that represent the 'path of least surprise', it's developers that think users want a 'beautiful, clever' GUI (and that they can design one). Why on earth would they want such a control over a standard toggle-button?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 4
    A toggle button like that imitates a real physical switch, so as long as the user knows what to expect when they interact with it, there will be minimal surprise in effect. +1 for `JToggleButton`, it's an easier way to go about it and would save time not having to re-invent it. – rtheunissen Feb 05 '12 at 03:46
  • @paranoid-android So long as it is a normal component of the OS, it is no longer the path of least surprise. OTOH I argue it is just one way (and not necessarily the best) to represent a 'toggleable switch'. A toggle button or check-box are two other ways. – Andrew Thompson Feb 05 '12 at 03:57
  • It's simply `have the component do what the user would expect from it`. And @MK., you have the right to your opinion and this isn't the place for an argument so I'll let it slide. :p Agreed that if it adheres to the style of the other components, you'll be safe. Seeing as this question is regarding Swing, whether or not this kind of switch would 'fit in' is completely up to the implementation. – rtheunissen Feb 05 '12 at 04:02
  • @MK. I don't use OS X, but think the look is very elegant. Further, given the Apple attitude towards honing the user experience, I very much doubt they would be non-intuitive. So 'you have the right to your opinion, but please don't clutter this thread with it'. Comment flagged as unconstructive. – Andrew Thompson Feb 05 '12 at 04:09
  • @AndrewThompson You are 100% right, that's why I said it was amazingly non-intuitive -- given the visual perfection and amount of detail, the results are underwhelming to say the least. – MK. Feb 05 '12 at 04:24
  • When using two icons to represent on & off, it will not behave as a user expects. With such a kind of switch, a user expects it needs to drag the slider from left to right (or vice versa), and that (s)he sees the slider moving (which it does on OS X). You will never get that effect with a `JToggleButton` with two icons – Robin Feb 05 '12 at 09:58
  • @Robin you could easily get that effect simply by overriding `paintComponent` of a `JLabel` and two `MouseListener` instances (`MouseMotion` and `Mouse`), with a small amount of algebra. – rtheunissen Feb 05 '12 at 11:02
9

I don't know of a standard one, but Gerrit Grunwald who creates the Steel Series components created an implementation of this that he calls a Steel Checkbox

Steel checkbox

Tim Sparg
  • 3,294
  • 2
  • 27
  • 40
7

Guess I am 6 years late, but nevertheless for those who still search for a simple solution:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.Cursor;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class ToggleSwitch extends JPanel {
    private boolean activated = false;
    private Color switchColor = new Color(200, 200, 200), buttonColor = new Color(255, 255, 255), borderColor = new Color(50, 50, 50);
    private Color activeSwitch = new Color(0, 125, 255);
    private BufferedImage puffer;
    private int borderRadius = 10;
    private Graphics2D g;
    public ToggleSwitch() {
        super();
        setVisible(true);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent arg0) {
                activated = !activated;
                repaint();
            }
        });
        setCursor(new Cursor(Cursor.HAND_CURSOR));
        setBounds(0, 0, 41, 21);
    }
    @Override
    public void paint(Graphics gr) {
        if(g == null || puffer.getWidth() != getWidth() || puffer.getHeight() != getHeight()) {
            puffer = (BufferedImage) createImage(getWidth(), getHeight());
            g = (Graphics2D)puffer.getGraphics();
            RenderingHints rh = new RenderingHints(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHints(rh);
        }
        g.setColor(activated?activeSwitch:switchColor);
        g.fillRoundRect(0, 0, this.getWidth()-1,getHeight()-1, 5, borderRadius);
        g.setColor(borderColor);
        g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 5, borderRadius);
        g.setColor(buttonColor);
        if(activated) {
            g.fillRoundRect(getWidth()/2, 1,  (getWidth()-1)/2 -2, (getHeight()-1) - 2,  borderRadius, borderRadius);
            g.setColor(borderColor);
            g.drawRoundRect((getWidth()-1)/2, 0, (getWidth()-1)/2, (getHeight()-1), borderRadius, borderRadius);
        }
        else {
            g.fillRoundRect(1, 1, (getWidth()-1)/2 -2, (getHeight()-1) - 2,  borderRadius, borderRadius);
            g.setColor(borderColor);
            g.drawRoundRect(0, 0, (getWidth()-1)/2, (getHeight()-1), borderRadius, borderRadius);
        }

        gr.drawImage(puffer, 0, 0, null);
    }
    public boolean isActivated() {
        return activated;
    }
    public void setActivated(boolean activated) {
        this.activated = activated;
    }
    public Color getSwitchColor() {
        return switchColor;
    }
    /**
     * Unactivated Background Color of switch
     */
    public void setSwitchColor(Color switchColor) {
        this.switchColor = switchColor;
    }
    public Color getButtonColor() {
        return buttonColor;
    }
    /**
     * Switch-Button color
     */
    public void setButtonColor(Color buttonColor) {
        this.buttonColor = buttonColor;
    }
    public Color getBorderColor() {
        return borderColor;
    }
    /**
     * Border-color of whole switch and switch-button
     */
    public void setBorderColor(Color borderColor) {
        this.borderColor = borderColor;
    }
    public Color getActiveSwitch() {
        return activeSwitch;
    }
    public void setActiveSwitch(Color activeSwitch) {
        this.activeSwitch = activeSwitch;
    }
    /**
     * @return the borderRadius
     */
    public int getBorderRadius() {
        return borderRadius;
    }
    /**
     * @param borderRadius the borderRadius to set
     */
    public void setBorderRadius(int borderRadius) {
        this.borderRadius = borderRadius;
    }

}

Just copy it in a ToggleSwitch.java. You can add it to your JFrame like this:

ToggleSwitch ts = new ToggleSwitch();
ts.setLocation(5, 135);
frame.add(ts);
Frobeniusnorm
  • 81
  • 1
  • 3
  • The toggle looks good. Is there a way to add a text within the toggle? – Liso Apr 15 '20 at 19:13
  • Necropost, but anyone who still has @Liso 's question, you can add a drawText call inside of the paint method of this class. – Chspsa Jan 03 '23 at 22:09
5

Swing doesn't have a standard switch like the one you described. Your best bet if you can't find a third party one would be to simply write one. The way I'd approach it would be a simple structure like this:

JLabel
• Override paintComponent
• Check for state with something like isOn()
• Add a MouseListener to toggle state.
• Custom painting would take into account label values and sizes.

I could send you one that I wrote some time ago, but you probably have a very specific idea of what you want so might be worth the half an hour constructing it.

rtheunissen
  • 7,347
  • 5
  • 34
  • 65