8

JDK 7 为JColorChooser添加了一个新的透明度滑块:

在此处输入图像描述

问题是我不想让我的用户选择透明颜色。不幸的是,似乎没有一种简单的方法可以禁用滑块。

摆脱透明度的一种方法是仅根据所选颜色创建一种新颜色,但删除 alpha 值。然而,这会给用户一个错误的印象,因为滑块现在实际上什么都不做,我讨厌周围有一个无用的 UI 元素。

所以我的问题是,摆脱透明度滑块的最佳方法是什么?

PS:IMO,奇怪的是他们只会添加滑块并使其成为默认行为。这可能会导致 JDK 6 程序中的许多错误,这些错误不希望颜色选择器返回具有 alpha 值的颜色。

4

5 回答 5

5

根据文档,可以只修改/配置现有的类。因此,推荐的方法是创建自己的选择器面板(它们需要扩展AbstractColorChooserPanel),然后调用

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

或者,如果您正在寻找一种更快/更糟糕/更丑陋的方式来做到这一点,请为您写下:

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);
    }
}

祝你好运:)

于 2012-08-19T14:57:20.077 回答
3

尽管它依赖于实现,但您可以AbstractColorChooserPanel按名称删除具体的子类。

此示例删除除 RGB 面板之外的所有面板:

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);
}

此示例恢复 HSB 面板:

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

您需要根据经验确定所需的名称。

于 2012-08-19T15:20:49.857 回答
1

这是对 aymeric 答案的轻微修改,将它们完全隐藏而不是禁用。

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);
    }
}
于 2014-03-24T12:03:09.763 回答
1

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];
    }
}
于 2014-07-21T22:01:29.687 回答
0

Java 9添加了一个新属性AbstractColorChooserPanel来控制这些滑块:

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

还有一个新的静态JColorChooser.showDialog方法重载来指定相同的属性:

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

Java 9预计将于2017 年 3 月发布。

于 2016-05-01T03:34:14.727 回答