Java 7 JColorChooser: Disable Transparency Slider
Asked Answered
U

5

10

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.

Urena answered 19/8, 2012 at 13:16 Comment(0)
I
5

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

Intrepid answered 19/8, 2012 at 14:57 Comment(0)
D
3

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.

Dubiety answered 19/8, 2012 at 15:20 Comment(0)
A
2

The other answers here show how to remove the transparency sliders from an instance of JColorChooser, but the main way to use JColorChooser is the static showDialog method, in which case you don't get access to an instance. Therefore I present two methods, one which hides the controls from an instance of JColorChooser, and a drop-in replacement method for showDialog that has showTransparencyControls as a extra parameter:

import java.awt.*;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.swing.*;
import javax.swing.colorchooser.AbstractColorChooserPanel;

class SwingUtil {
    /**
     * Hides controls for configuring color transparency on the specified
     * color chooser.
     */
    public static void hideTransparencyControls(JColorChooser cc) {
        AbstractColorChooserPanel[] colorPanels = cc.getChooserPanels();
        for (int i = 0; i < colorPanels.length; i++) {
            AbstractColorChooserPanel cp = colorPanels[i];
            try {
                Field f = cp.getClass().getDeclaredField("panel");
                f.setAccessible(true);
                Object colorPanel = f.get(cp);

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

                Object transparencySlider = java.lang.reflect.Array.get(sliders, 3);
                if (i == colorPanels.length - 1)
                    transparencySlider = java.lang.reflect.Array.get(sliders, 4);

                Method setVisible = transparencySlider.getClass().getDeclaredMethod(
                    "setVisible", boolean.class);
                setVisible.setAccessible(true);
                setVisible.invoke(transparencySlider, false);
            } catch (Throwable t) {}
        }
    }


    /**
     * Shows a modal color chooser dialog and blocks until the dialog is
     * closed.
     * 
     * @param component the parent component for the dialog; may be null
     * @param title the dialog's title
     * @param initialColor the initial color set when the dialog is shown
     * @param showTransparencyControls whether to show controls for
     *        configuring the color's transparency
     * @return the chosen color or null if the user canceled the dialog
     */
    public static Color showColorChooserDialog(Component component,
            String title, Color initialColor, boolean showTransparencyControls) {
        JColorChooser pane = new JColorChooser(
            initialColor != null ? initialColor : Color.white);
        if (!showTransparencyControls) hideTransparencyControls(pane);
        Color[] result = new Color[1];
        ActionListener okListener = e -> result[0] = pane.getColor();
        JDialog dialog = pane.createDialog(component, title, true, pane, okListener, null);
        dialog.setVisible(true);
        dialog.dispose();
        return result[0];
    }
}
Aholla answered 21/7, 2014 at 22:1 Comment(0)
M
1

Here is a slight modification of aymeric's answer that hides them altogether instead of disabling.

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);
        slider.setVisible(false);
        Field f4 = transpSlispinner.getClass().getDeclaredField("spinner");
        f4.setAccessible(true);
        JSpinner spinner = (JSpinner) f4.get(transpSlispinner);
        spinner.setEnabled(false);
        spinner.setVisible(false);

        Field f5 = transpSlispinner.getClass().getDeclaredField("label");
        f5.setAccessible(true);
        JLabel label = (JLabel) f5.get(transpSlispinner);
        label.setVisible(false);
    }
}
Mar answered 24/3, 2014 at 12:3 Comment(0)
A
1

Java 9 adds a new property to AbstractColorChooserPanel to control these sliders:

public void setColorTransparencySelectionEnabled(boolean b);
public boolean isColorTransparencySelectionEnabled();

There is also a new overload of the static JColorChooser.showDialog method to specify that same property:

public static Color showDialog(Component component, String title, Color initialColor,
    boolean colorTransparencySelectionEnabled);

Java 9 is expected to be released in March 2017.

Aholla answered 1/5, 2016 at 3:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.