Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 7 JColorChooser: Disable Transparency Slider

JDK 7 added a new transparency slider to the JColorChooser:

enter image description here

The problem is that I do not want to allow my users to pick transparent colors. Unfortunately, there doesn't seem to be an easy way to disable the slider.

One way to get rid of the transparency is to just create a new color based on the selected one but removing the alpha value. However, this gives a false impression to the user as the slider now effectively does nothing and I would hate to have a useless UI element around.

So my question is, what's the best way to get rid of the transparency slider?

P.S.: IMO, it's weird that they would just add the slider and make it the default behavior. This might cause a lot of bugs in JDK 6 programs that do not expect the color chooser to return a color with an alpha value.

like image 373
jhenninger Avatar asked Aug 19 '12 13:08

jhenninger


2 Answers

According to the documentation, it's possible to just modify/configure the existing classes. So recommended way to go is therefore to create your own ChooserPanels (they need to extend AbstractColorChooserPanel) and then invoke

JColorChooser jc = new JColorChooser();
jc.setChooserPanels(new AbstractColorChooserPanel[]{yourChooserPanel});

Alternatively, if yor aree looking for a faster/nastier/uglier way to do it, wrote this for you:

private static void removeTransparencySlider(JColorChooser jc) throws Exception {

    AbstractColorChooserPanel[] colorPanels = jc.getChooserPanels();
    for (int i = 1; i < colorPanels.length; i++) {
        AbstractColorChooserPanel cp = colorPanels[i];

        Field f = cp.getClass().getDeclaredField("panel");
        f.setAccessible(true);

        Object colorPanel = f.get(cp);
        Field f2 = colorPanel.getClass().getDeclaredField("spinners");
        f2.setAccessible(true);
        Object spinners = f2.get(colorPanel);

        Object transpSlispinner = Array.get(spinners, 3);
        if (i == colorPanels.length - 1) {
            transpSlispinner = Array.get(spinners, 4);
        }
        Field f3 = transpSlispinner.getClass().getDeclaredField("slider");
        f3.setAccessible(true);
        JSlider slider = (JSlider) f3.get(transpSlispinner);
        slider.setEnabled(false);
        Field f4 = transpSlispinner.getClass().getDeclaredField("spinner");
        f4.setAccessible(true);
        JSpinner spinner = (JSpinner) f4.get(transpSlispinner);
        spinner.setEnabled(false);
    }
}

Good luck with it :)

like image 177
aymeric Avatar answered Oct 29 '22 12:10

aymeric


Although it's implementation dependent, you can remove concrete subclasses of AbstractColorChooserPanel by name.

This example removes all but the RGB panel:

AbstractColorChooserPanel[] ccPanels = chooser.getChooserPanels();
for (AbstractColorChooserPanel ccPanel : ccPanels) {
    System.out.println(ccPanel.getDisplayName());
    String name = ccPanel.getClass().getSimpleName();
    if (!"DefaultRGBChooserPanel".equals(name))
        tcc.removeChooserPanel(ccPanel);
}

This example restores the HSB panel:

for (AbstractColorChooserPanel ccPanel : ccPanels) {
    String name = ccPanel.getClass().getSimpleName();
    if ("DefaultHSBChooserPanel".equals(name))
        tcc.addChooserPanel(ccPanel);
}

You'll need to determine the desired name(s) empirically.

like image 24
trashgod Avatar answered Oct 29 '22 14:10

trashgod