Open Poivin opened 4 years ago
Do you mean something like this?
Yes, this is coming to FlatLaf, when I find some free time... Currently focusing on fixing last issues before releasing FlatLaf 1.0.
The plan is to implement such switches based on JToggleButton
.
If you need it for JCheckBox
now, you can do this easily by implementing a icon class (implements javax.swing.Icon
) that paints the two states. Icon.paintIcon(Component, Graphics, int, int)
receives the checkbox as first argument and you can use ((JCheckBox)c).isSelected()
to decide what state to paint. Then use JCheckBox.setIcon( icon )
to assign the switch icon to a checkbox.
Awesome, ok thanks Karl. I put CheckBox but if it is a toggleButton it is good as well! A question about color because your exemple illustrate for me a On/off feature or a activate/deactivate. but i think users could be also interested in a neutral binary widget without changing its color. For exemple for a switch of display 2D <==> 3D .
Keep up the good work as you do since beginning of this great LaF! And good luck for flatLaf 1.0
Hello, All.
On one of our projects, taking FlatCheckBoxIcon as a basis, we use such an icon for our component.
Set the icon to JCheckBox
Sample code
class SwitchIcon extends FlatCheckBoxIcon {
private static final int ICON_WIDTH = 28;
private static final int ICON_HEIGHT = 16;
private final static int KNOB_WIDTH = ICON_WIDTH / 2 - 2;
private final static int KNOB_HEIGHT = ICON_HEIGHT - 5;
public SwitchIcon() {
super();
}
protected void paintBorder(Graphics2D g2) {
int arcwh = arc;
g2.fillRoundRect(3, 0, ICON_WIDTH - 1, ICON_HEIGHT - 1, arcwh, arcwh);
}
protected void paintBackground(Graphics2D g2) {
int arcwh = arc - 1;
g2.fillRoundRect(4, 1, ICON_WIDTH - 3, ICON_HEIGHT - 3, arcwh, arcwh);
}
protected void paintCheckmark(Graphics2D g2) {
int arcwh = arc - 1;
g2.fillRoundRect(5, 2, KNOB_WIDTH, KNOB_HEIGHT, arcwh, arcwh);
}
@Override
protected void paintIcon(Component c, Graphics2D g2) {
boolean selected = (c instanceof AbstractButton && ((AbstractButton) c).isSelected());
super.paintIcon(c, g2);
if (!selected) {
g2.setColor(disabledCheckmarkColor);
int x = KNOB_WIDTH - 1;
g2.translate(x, 0);
paintCheckmark(g2);
g2.translate(-(x), 0);
}
}
@Override
public int getIconWidth() {
return ICON_WIDTH;
}
@Override
public int getIconHeight() {
return ICON_HEIGHT;
}
}
@dinix2008 awesome, thanks for sharing π
But shouldn't the blue knob placed on the right side if selected? Usually knob is on the left if switch is off, and on the right if on.
@Poivin wrote:
A question about color because your exemple illustrate for me a On/off feature or a activate/deactivate
The switches in the image are taken from Windows 10 just as a sample. I'm not gonna use this style in FlatLaf because it does not fit to the overall style.
@DevCharly
But shouldn't the blue knob placed on the right side if selected? Usually knob is on the left if switch is off, and on the right if on.
On your advice, I corrected the position of the knob and set the radius fixedly equal to the width of the icon, it turned out like this:
class SwitchIcon extends FlatCheckBoxIcon {
private static final int ICON_WIDTH = 28;
private static final int ICON_HEIGHT = 16;
private final static int KNOB_WIDTH = ICON_WIDTH / 2 - 2;
private final static int KNOB_HEIGHT = ICON_HEIGHT - 5;
protected final int arc = ICON_HEIGHT;
public SwitchIcon() {
super();
}
protected void paintBorder(Graphics2D g2) {
int arcwh = arc;
g2.fillRoundRect(3, 0, ICON_WIDTH - 1, ICON_HEIGHT - 1, arcwh, arcwh);
}
protected void paintBackground(Graphics2D g2) {
int arcwh = arc - 1;
g2.fillRoundRect(4, 1, ICON_WIDTH - 3, ICON_HEIGHT - 3, arcwh, arcwh);
}
protected void paintCheckmark(Graphics2D g2) {
int arcwh = arc - 1;
int x = KNOB_WIDTH - 1;
g2.translate(x, 0);
g2.fillRoundRect(5, 2, KNOB_WIDTH, KNOB_HEIGHT, arcwh, arcwh);
g2.translate(-(x), 0);
}
@Override
protected void paintIcon(Component c, Graphics2D g2) {
boolean selected = (c instanceof AbstractButton && ((AbstractButton) c).isSelected());
super.paintIcon(c, g2);
if (!selected) {
g2.setColor(disabledCheckmarkColor);
int x = KNOB_WIDTH - 1;
g2.translate(-x, 0);
paintCheckmark(g2);
g2.translate(+(x), 0);
}
}
@Override
public int getIconWidth() {
return ICON_WIDTH;
}
@Override
public int getIconHeight() {
return ICON_HEIGHT;
}
}
Thanks for this @dinix2008. I integrated it with my application, but I'm seeing the colour behind the left hand side of the switch after pressing it once.
This is Flat Light
It seems related to the colour of the theme as well. This is Monokai Pro Contrast
This is dark purple
@grimlock81 I've only tested on FlatLightLaf / FlatDarkLaf. Made the necessary fixes and now on FlatDarculaLaf / FlatIntelliJLaf it is also displayed corrected
class SwitchIcon extends FlatCheckBoxIcon {
private static final int ICON_WIDTH = 28;
private static final int ICON_HEIGHT = 16;
private final static int KNOB_WIDTH = ICON_WIDTH / 2 - 2;
private final static int KNOB_HEIGHT = ICON_HEIGHT - 5;
protected final int arc = ICON_HEIGHT;
public SwitchIcon() {
super();
}
protected void paintBorder(Graphics2D g2) {
int arcwh = arc;
g2.fillRoundRect(3, 0, ICON_WIDTH - 1, ICON_HEIGHT - 1, arcwh, arcwh);
}
protected void paintBackground(Graphics2D g2) {
int arcwh = arc - 1;
g2.fillRoundRect(4, 1, ICON_WIDTH - 3, ICON_HEIGHT - 3, arcwh, arcwh);
}
protected void paintCheckmark(Graphics2D g2) {
int arcwh = arc - 1;
int x = KNOB_WIDTH - 1;
g2.translate(x, 0);
g2.fillRoundRect(5, 2, KNOB_WIDTH, KNOB_HEIGHT, arcwh, arcwh);
g2.translate(-(x), 0);
}
@Override
protected void paintFocusBorder(Graphics2D g2) {
int w = getIconWidth() - 1 + (focusWidth * 2);
int h = getIconHeight() - 1 + (focusWidth * 2);
int arcwh = arc + (focusWidth * 2);
g2.fillRoundRect(-focusWidth + 3, -focusWidth, w, h, arcwh, arcwh);
}
@Override
protected void paintIndeterminate(Graphics2D g2) {
super.paintIndeterminate(g2);
}
@Override
protected void paintIcon(Component c, Graphics2D g2) {
boolean selected = (c instanceof AbstractButton && ((AbstractButton) c).isSelected());
super.paintIcon(c, g2);
if (!selected) {
g2.setColor(disabledCheckmarkColor);
int x = KNOB_WIDTH - 1;
g2.translate(-x, 0);
paintCheckmark(g2);
g2.translate(x, 0);
}
}
@Override
public int getIconWidth() {
return ICON_WIDTH;
}
@Override
public int getIconHeight() {
return ICON_HEIGHT;
}
}
Thanks again @dinix2008. I've tried it on a few themes and they all look perfect.
BTW, if anyone is interested, to make the switch respect the arc property "CheckBox.arc"
remove this line
protected final int arc = ICON_HEIGHT;
and arc variable will be inherited from the superclass. But the depending on the value set it may not look as nice as the dinix2008's version.
Hi @DevCharly, is there still the plan to integrate the toggle switch directly into FlatLaf? Either as a separate control, as a toggle button style or as a checkbox icon.
Hello. Will be nice to have it :) Waiting this style of button too
Hi,
Is there a way in flatLAF to give to checkbox the appearance of a switch widget ? It is useful when we need a binary widget out of True/false entries. Do you think it could be part of the look and feel? I don't think that Java proposes widget like that (Java 1.8 almost).