Is there a standard GUI toggle switch in Java?
Asked Answered
H

4

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.)

Homogamy answered 5/2, 2012 at 3:29 Comment(1)
Related examples may be found here and here.Mangonel
C
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?

Crick answered 5/2, 2012 at 3:39 Comment(7)
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.Wiggs
@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.Crick
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.Wiggs
@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.Crick
@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.Gustative
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 iconsAtalanti
@Atalanti 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.Wiggs
D
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

Dissemblance answered 24/3, 2012 at 11:51 Comment(2)
Gerrit's blog is a great resource. Thanks!Homogamy
that's good. but i hope someone would put the tutorial step by step for the Gerrit's library. right @Homogamy ?Abm
L
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);
Lavallee answered 20/9, 2018 at 9:1 Comment(2)
The toggle looks good. Is there a way to add a text within the toggle?Samalla
Necropost, but anyone who still has @Samalla 's question, you can add a drawText call inside of the paint method of this class.Proteolysis
W
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.

Wiggs answered 5/2, 2012 at 3:39 Comment(1)
Implementing Icon is also convenient way to change the appearance.Mangonel

© 2022 - 2024 — McMap. All rights reserved.