【问题标题】:Java 7 JColorChooser: Disable Transparency SliderJava 7 JColorChooser:禁用透明度滑块
【发布时间】:2012-08-15 03:22:00
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: java swing transparency java-7 jcolorchooser


    【解决方案1】:

    根据文档,可以只修改/配置现有的类。所以推荐的方法是创建你自己的ChooserPanels(他们需要扩展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);
        }
    }
    

    祝你好运:)

    【讨论】:

      【解决方案2】:

      虽然它依赖于实现,但您可以按名称删除 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);
      }
      

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

      【讨论】:

        【解决方案3】:

        这是对 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);
            }
        }
        

        【讨论】:

          【解决方案4】:

          此处的其他答案显示了如何从 JColorChooser 实例中删除透明度滑块,但使用 JColorChooser 的主要方法是静态 showDialog 方法,在这种情况下您无法访问实例。因此,我提出了两种方法,一种是隐藏 JColorChooser 实例中的控件,另一种是 showDialog 的替代方法,其中 showTransparencyControls 作为额外参数:

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

          【讨论】:

            【解决方案5】:

            Java 9 adds 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 月是 expected to be released

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-11-28
              • 2018-12-17
              • 1970-01-01
              • 2015-05-03
              • 2013-02-20
              • 1970-01-01
              • 2012-11-24
              • 1970-01-01
              相关资源
              最近更新 更多