How to show only HSV JColorChooser field?

In this image you can see the standard range of the Swing the Java, JColorChooser

:

Default Java

I only want a square of color and a vertical slider as shown in red:

What I want

I was able to remove all tabs (Swatches, HSL, etc.) and previews, but I was unable to remove all sliders. How can i do this?

+3


source to share


4 answers


OK, just for a laugh, I decided to create the desired JPanel from scratch by hooking it into the view as a View-Controller, since the model is trivial here - a color field inside the controller. To use this component, you instantiate the component, add it to your GUI whenever you want, and simply add a PropertyChangeListener to it that listens for its COLOR property:

hsvChooserPanel.addPropertyChangeListener(HsvChooserPanel.COLOR, pce -> {
    Color c = (Color) pce.getNewValue();
    // do what you want with Color value, c, here
});

      

Test class:


Version 2: This allows any 3 HSV bar / bar combination combinations, either one with a hue-oriented bar or saturation or value (here Brightness). It uses an enum, ColorProperty, which has 3 values, ColorProperty.HUE, ColorProperty.SATURATION and ColorProperty.BRIGHTNESS, and calculations in the enumeration elements themselves on how to create a color bar and color square BufferedImages. Comments are welcome:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestHsvChooser2 {
    // ***** choose which color panel / color bar you'd like to test:
    // private static final ColorProperty COLOR_PROP = ColorProperty.HUE;
    // private static final ColorProperty COLOR_PROP = ColorProperty.BRIGHTNESS;
    private static final ColorProperty COLOR_PROP = ColorProperty.SATURATION;

    private static void createAndShowGui() {
        HsvChooserPanel2 hsvChooserPanel = new HsvChooserPanel2(COLOR_PROP);

        JPanel testPanel = new JPanel();
        JPanel outerPanel = new JPanel(new BorderLayout());
        outerPanel.add(testPanel);
        outerPanel.setBorder(BorderFactory.createTitledBorder("Test Panel"));

        hsvChooserPanel.addPropertyChangeListener(HsvChooserPanel2.COLOR, pce -> {
            Color c = (Color) pce.getNewValue();
            testPanel.setBackground(c);
        });

        JPanel gridPanel = new JPanel(new GridLayout(0, 1, 10, 10));
        gridPanel.add(hsvChooserPanel);
        gridPanel.add(outerPanel);

        JFrame frame = new JFrame("HSV Chooser");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(gridPanel);
        frame.setResizable(false);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

      

The whole shebang:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.SwingPropertyChangeSupport;

@SuppressWarnings("serial")
public class HsvChooserPanel2 extends JPanel {
    public static final String COLOR = "color";
    private static final int PREF_W = 180;
    private static final int PREF_H = PREF_W;
    private static final int PREF_W_CB = 20;
    private static final int GAP = 10;
    private MyColorPanel2 colorPanel = null;
    private MyColorBar2 colorBar = null;
    private InnerControl2 innerControl = null;

    public HsvChooserPanel2(ColorProperty colorProp) {
        colorPanel = new MyColorPanel2(PREF_W, PREF_H, colorProp);
        colorBar = new MyColorBar2(PREF_W_CB, PREF_H, colorProp);
        innerControl = new InnerControl2(this, colorPanel, colorBar);
        colorPanel.setColorPropertyValue(Color.RED); // !! magic value
        setLayout(new BorderLayout(GAP, GAP));
        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        add(colorPanel, BorderLayout.CENTER);
        add(colorBar, BorderLayout.LINE_END);

        // propagate COLOR changes in the inner controller
        // to this component property change support
        innerControl.addPropertyChangeListener(COLOR, pce -> {
            firePropertyChange(COLOR, pce.getOldValue(), pce.getNewValue());
        });
    }


}

      



// listens for changes to both the color bar and the color panel
class InnerControl2 {
    private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);

    private HsvChooserPanel2 hsvChooser;
    private MyColorPanel2 colorPanel;
    private MyColorBar2 colorBar;
    private Color color; // This is all there is to the model, a "bound"
                         // property

    public InnerControl2(HsvChooserPanel2 hsvChooser, MyColorPanel2 colorPanel, MyColorBar2 colorBar) {
        this.hsvChooser = hsvChooser;
        this.colorPanel = colorPanel;
        this.colorBar = colorBar;

        // listen for changes
        colorPanel.addPropertyChangeListener(ColorPanelParent.CURSOR, new ColorPanelListener());
        colorBar.addPropertyChangeListener(ColorPanelParent.CURSOR, new ColorBarListener());
    }

    public Color getColor() {
        return color;
    }

    // classic setter method for a "bound" property
    public void setColor(Color color) {
        Color oldValue = this.color;
        Color newValue = color;
        this.color = color;
        // notify listeners of the change
        pcSupport.firePropertyChange(HsvChooserPanel2.COLOR, oldValue, newValue);
    }

    // allow outside classes the ability to listen
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        pcSupport.removePropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
        pcSupport.addPropertyChangeListener(name, listener);
    }

    public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
        pcSupport.removePropertyChangeListener(name, listener);
    }

    public HsvChooserPanel2 getHsvChooser() {
        return hsvChooser;
    }

    // inner listeners
    private class ColorPanelListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Point p = colorPanel.getCursorP();
            Color c = colorPanel.getColor(p);
            colorBar.setColorPropertyValue(c);
            setColor(c); // this will fire the prop change
                                              // support
        }
    }

    private class ColorBarListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            // get hue from the color bar and use it to set the main hue
            // of the color panel
            Point p = colorBar.getCursorP();
            Color c = colorBar.getColor(p);
            colorPanel.setColorPropertyValue(c);
        }
    }
}

      



// parent of both color bar panel and color panel
@SuppressWarnings("serial")
abstract class ColorPanelParent extends JPanel {
    public static final String CURSOR = "cursor";
    private int prefW;
    private int prefH;
    private Point cursorP = new Point(0, 0);
    private BufferedImage img = null;
    private ColorProperty colorProperty;
    private boolean panel;

    public ColorPanelParent(int prefW, int prefH, ColorProperty colorProperty, boolean panel) {
        this.prefW = prefW;
        this.prefH = prefH;
        this.colorProperty = colorProperty;
        this.panel = panel;
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(prefW, prefH);
    }

    public int getPrefH() {
        return prefH;
    }

    public int getPrefW() {
        return prefW;
    }

    public ColorProperty getColorProperty() {
        return colorProperty;
    }

    public BufferedImage getImg() {
        return img;
    }

    public Point getCursorP() {
        return cursorP;
    }

    public void setImg(BufferedImage img) {
        this.img = img;
        repaint();
    }

    public Color getColor(Point p) {
        Color c = null;
        if (getImg() != null) {
            int rgb = getImg().getRGB(p.x, p.y);
            c = new Color(rgb);
        }
        return c;
    }

    // when the main hue is changed, we have to create a new
    // background image to reflect the new main color
    public void setColorPropertyValue(Color color) {
        int w = getPrefW();
        int h = getPrefH();
        BufferedImage img = getColorProperty().createImage(color, w, h, panel);
        setImg(img);
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (img != null) {
            g.drawImage(img, 0, 0, this);
        }
    }

    // change the cursor point and then
    // notify prop change support of changes
    private class MyMouse extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
            mouseResponse(e);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            mouseResponse(e);
        }

        private void mouseResponse(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            if (!contains(e.getPoint())) {
                x = Math.max(0, x);
                x = Math.min(prefW - 1, x);
                y = Math.max(0, y);
                y = Math.min(prefH - 1, y);
            }
            Point oldValue = cursorP;
            cursorP = new Point(x, y);
            firePropertyChange(CURSOR, oldValue, cursorP);
            repaint();
        }
    }

}

      



// color bar on the right side of the HsvChooser JPanel.
// Controller action: Changing selection point on this JPanel
// will change the hue of the color panel
@SuppressWarnings("serial")
class MyColorBar2 extends ColorPanelParent {

    public MyColorBar2(int prefW, int prefH, ColorProperty colorProperty) {
        super(prefW, prefH, colorProperty, false);

        // create and set the background image
        setColorPropertyValue(Color.RED); // fix the magic number?
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // draws the background image

        // this draws a line at the cursor location
        g.setXORMode(Color.WHITE);
        int y = getCursorP().y;
        g.drawLine(0, y, getPrefW(), y);
    }

}

      



// color panel on the left side of the HsvChooser JPanel.
// Controller action: Changing selection point on this JPanel
// will notify listeners of a new COLOR selection
@SuppressWarnings("serial")
class MyColorPanel2 extends ColorPanelParent {
    private static final int CURSOR_RADIUS = 8;

    public MyColorPanel2(int prefW, int prefH, ColorProperty colorProperty) {
        super(prefW, prefH, colorProperty, true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // draws the background image

        // draws the cross hatch indicating color selection point
        g.setXORMode(Color.WHITE);
        int x = getCursorP().x;
        int y = getCursorP().y;
        int x1 = x - CURSOR_RADIUS;
        int y1 = y - CURSOR_RADIUS;
        int x2 = x + CURSOR_RADIUS;
        int y2 = y + CURSOR_RADIUS;
        g.drawLine(x1, y, x2, y);
        g.drawLine(x, y1, x, y2);
    }
}

      



enum ColorProperty {
    HUE {
        @Override
        public BufferedImage createImage(Color color, int w, int h, boolean panel) {
            BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

            if (panel) {
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                // float array is HSB
                float hue = Color.RGBtoHSB(red, green, blue, null)[0]; 

                for (int i = 0; i < h; i++) {
                    for (int j = 0; j < w; j++) {
                        float s = ((float) j) / (float) w;
                        float b = (h - (float) i) / (float) h;
                        int rgb = Color.getHSBColor(hue, s, b).getRGB();
                        img.setRGB(j, i, rgb);
                    }
                }
            } else {
                for (int i = 0; i < h; i++) {
                    for (int j = 0; j < w; j++) {
                        float hue = (h - (float) i) / (float) h;
                        int rgb = Color.getHSBColor(hue, 1f, 1f).getRGB();
                        img.setRGB(j, i, rgb);
                    }
                }
            }
            return img;
        }
    },
    SATURATION {
        @Override
        public BufferedImage createImage(Color color, int w, int h, boolean panel) {
            BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            int red = color.getRed();
            int green = color.getGreen();
            int blue = color.getBlue();
            // float array is HSB
            float[] hsb = Color.RGBtoHSB(red, green, blue, null);

            return panel ? createPanelImg(w, h, img, hsb) : createBarImg(w, h, img, hsb);
        }

        private BufferedImage createBarImg(int w, int h, BufferedImage img, float[] hsb) {
            float hue = hsb[0];
            // float brightness = hsb[2];
            float brightness = 1f;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    float saturation = (h - (float) i) / (float) h;
                    int rgb = Color.getHSBColor(hue, saturation, brightness).getRGB();
                    img.setRGB(j, i, rgb);
                }
            }
            return img;
        }

        private BufferedImage createPanelImg(int w, int h, BufferedImage img, float[] hsb) {
            float saturation = hsb[1]; 
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    float hue = ((float) j) / (float) w;
                    float b = (h - (float) i) / (float) h;
                    int rgb = Color.getHSBColor(hue, saturation, b).getRGB();
                    img.setRGB(j, i, rgb);
                }
            }            
            return img;
        }
    },
    BRIGHTNESS {
        @Override
        public BufferedImage createImage(Color color, int w, int h, boolean panel) {
            BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            int red = color.getRed();
            int green = color.getGreen();
            int blue = color.getBlue();
            // float array is HSB
            float[] hsb = Color.RGBtoHSB(red, green, blue, null);

            return panel ? createPanelImg(w, h, img, hsb) : createBarImg(w, h, img, hsb);
        }

        private BufferedImage createBarImg(int w, int h, BufferedImage img, float[] hsb) {
            float hue = hsb[0];
            // float saturation = hsb[1];
            float saturation = 1f;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    float brightness = (h - (float) i) / (float) h;
                    int rgb = Color.getHSBColor(hue, saturation, brightness).getRGB();
                    img.setRGB(j, i, rgb);
                }
            }
            return img;
        }

        private BufferedImage createPanelImg(int w, int h, BufferedImage img, float[] hsb) {
            float brightness = hsb[2]; 
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    float hue = ((float) j) / (float) w;
                    float saturation = (h - (float) i) / (float) h;
                    int rgb = Color.getHSBColor(hue, saturation, brightness).getRGB();
                    img.setRGB(j, i, rgb);
                }
            }            
            return img;
        }
    };

    public abstract BufferedImage createImage(Color color, int w, int h, boolean panel);
}

      

+3


source


A look at the javax.swing.colorchooser

internals shows that it ColorChooserComponentFactory

subclasses AbstractColorChooserPanel

using ColorChooserPanel

and the appropriate subclass ColorModel

. ColorChooserPanel

contains the parts you want as two instances DiagramComponent

: the left name is called diagram

and the right one is slider

called.

Instead of removing components from an existing one, ColorChooserPanel

consider creating a custom picker that contains only the items you want .



class MyChooserPanel extends AbstractColorChooserPanel implements PropertyChangeListener {

    private final ColorModel model;
    private final DiagramComponent diagram;
    private final DiagramComponent slider;

    MyChooserPanel(ColorModel model) {
        this.model = model;
        this.diagram = new DiagramComponent(this.panel, true);
        this.slider = new DiagramComponent(this.panel, false);
    }
}

      

Naturally, you will have to repeat some of the (package-) private code, but the result will be less brittle.

+3


source


My decision:

        colorChooser.setPreviewPanel(new JPanel());
        AbstractColorChooserPanel[] panels = colorChooser.getChooserPanels();
        for (AbstractColorChooserPanel accp : panels) {
            if(!accp.getDisplayName().equals("HSV")) {
                colorChooser.removeChooserPanel(accp);
            } 
        }
        JComponent current = (JComponent) colorChooser.getComponents()[0];
        while( !current.getClass().toString().equals( "class javax.swing.colorchooser.ColorChooserPanel" ) ){
            current = (JComponent) current.getComponents()[0]; 
        }
        for(Component jc : current.getComponents()){
            if(!jc.getClass().toString().equals( "class javax.swing.colorchooser.DiagramComponent" )){
                current.remove(jc);
            }
        }  

      

This removes everything I don't want, but I think creating a custom one would be the best solution.
I'm going to try trashgod to see if it works better.

+3


source


You can use the Swing Utils class to find components of a given type in a panel.

In the example below, you can find all the sliders and then make them invisible:

import java.awt.*;
import java.util.List;
import javax.swing.*;
import javax.swing.colorchooser.*;

public class ColorChooserPanel extends JPanel
{
    ColorChooserPanel()
    {
        JColorChooser chooser = new JColorChooser();
        AbstractColorChooserPanel[] panels = chooser.getChooserPanels();

        for (AbstractColorChooserPanel panel: panels)
        {
            if ("HSL".equals(panel.getDisplayName()))
            {
                add( panel );

                List<JSlider> sliders = SwingUtils.getDescendantsOfType(JSlider.class, panel, true);

                for (JSlider slider: sliders)
                {
                    slider.setVisible( false );
                }

            }
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("ColorChooserPanel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new ColorChooserPanel());
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );

    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

      

+3


source







All Articles