Question

The size of color palette in JColorChooser/Swatches is very small, also the colors looks similar around a palette.

For my use I need to increase their size as well change the color variation. How to do this?

Was it helpful?

Solution

The size of the "swatches" is controlled by two UI properties, so you can adjust it as needed (default value being 10):

int length = 20;
UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(length, length));
UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(length, length));

Customizing the palette itself requires a custom subclass of AbstractColorChooserPanel, mainly a c&p job (because it's package private) of DefaultSwatchChooserPanel in javx.swing.colorchooser. Then replace the default with your custom panel, something along the lines

JColorChooser chooser = new JColorChooser();
List<AbstractColorChooserPanel> choosers = 
        new ArrayList<>(Arrays.asList(chooser.getChooserPanels()));
choosers.remove(0);
MySwatchChooserPanel swatch = new MySwatchChooserPanel();
choosers.add(0, swatch);
chooser.setChooserPanels(choosers.toArray(new AbstractColorChooserPanel[0]));

OTHER TIPS

  • [JColorChooser][1] is compound JComponent

  • you can to display/use only desired part of JColorChooser

  • for easier workaround to use SwingUtils by @Darryl Burke

enter image description here

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import javax.swing.event.*;
import javax.swing.plaf.metal.MetalComboBoxIcon;

public class DropDownComponent2 {

    private JWindow _window;
    private boolean _windowShouldBeShown = false;
    private JComponent _component;
    private AbstractButton _button;
    private JFrame _ownerFrame;

    public DropDownComponent2(JFrame ownerFrame, JComponent component, AbstractButton button) {
        _ownerFrame = ownerFrame;
        _component = component;
        _button = button;
        _button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                _window.setVisible(false);
                Point pt = _button.getLocationOnScreen();
                pt.translate(0, _button.getHeight());
                _window.setLocation(pt);
                showWindow();
                _windowShouldBeShown = true;
                Window[] wins = Window.getWindows();
                System.out.println(wins.length);
            }
        });
        _button.addAncestorListener(new AncestorListener() {
            @Override
            public void ancestorAdded(AncestorEvent event) {
                _window.setVisible(false);
            }

            @Override
            public void ancestorRemoved(AncestorEvent event) {
                _window.setVisible(false);
            }

            @Override
            public void ancestorMoved(AncestorEvent event) {
                if (event.getSource() != _window) {
                    System.out.println("Ansestor moved");
                    _window.setVisible(false);
                }
            }
        });
        Toolkit.getDefaultToolkit().addAWTEventListener(
                new AWTEventListener() {
                    @Override
                    public void eventDispatched(AWTEvent event) {
                        if (event.getID() == MouseEvent.MOUSE_CLICKED) {
                            if (!_window.getBounds().contains(MouseInfo.getPointerInfo().getLocation())) {
                                if (_windowShouldBeShown) {
                                    _windowShouldBeShown = false;
                                } else {
                                    _window.setVisible(false);
                                }
                            }
                        }
                    }
                }, AWTEvent.MOUSE_EVENT_MASK);
        _window = new JWindow(_ownerFrame);
        _window.getContentPane().add(component);
        _window.addWindowFocusListener(new WindowAdapter() {
            @Override
            public void windowLostFocus(WindowEvent evt) {
                System.out.println("window lost focus");
                _window.setVisible(false);
            }
        });
        _window.pack();
    }

    private Rectangle getScreenRect() {
        return new Rectangle(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
    }

    public void showWindow() {
        Rectangle screenRect = getScreenRect();
        Rectangle windowRect = _window.getBounds();
        int sx1 = screenRect.x;
        int sx2 = screenRect.x + screenRect.width;
        int sy1 = screenRect.y;
        int sy2 = screenRect.y + screenRect.height;
        int wx1 = windowRect.x;
        int wx2 = windowRect.x + windowRect.width;
        int wy1 = windowRect.y;
        int wy2 = windowRect.y + windowRect.height;
        if (wx2 > sx2) {
            _window.setLocation(wx1 - (wx2 - sx2), _window.getY());
        }
        if (wx1 < sx1) {
            _window.setLocation(0, _window.getY());
        }
        if (wy2 > sy2) {
            _window.setLocation(_window.getX(), wy1 - (wy2 - wy1));
        }
        if (wy2 < sy1) {
            _window.setLocation(_window.getX(), 0);
        }
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                _window.setVisible(true);
            }
        });
    }

    public void hideWindow() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                _window.setVisible(false);
            }
        });
    }
}

class DropDownFrame extends JFrame {

    private static final long serialVersionUID = 1L;
    private JButton _button;
    private JColorChooser _colorChooser;
    private DropDownComponent2 _dropDown;
    private JWindow _window;

    public DropDownFrame() {
        _colorChooser = new JColorChooser();
        _colorChooser.setPreviewPanel(new JPanel());
        _colorChooser.setColor(Color.RED);
        // Remove panels other than Swatches
        AbstractColorChooserPanel[] panels = _colorChooser.getChooserPanels();
        for (int i = 0; i < panels.length; i++) {
            if (!panels[i].getDisplayName().equals("Swatches")) {
                _colorChooser.removeChooserPanel(panels[i]);
            } else {
                JPanel panel = panels[i];
                System.out.println(panel.getComponentCount()); // 1
                System.out.println(panel.getPreferredSize()); //width=424,height=112
                System.out.println(panel.getLayout()); //FlowLayout[hgap=5,vgap=5,align=center]
            }
        }
        _colorChooser.getSelectionModel().addChangeListener(new ChangeListener() {
            @Override // ### I think the key point is there
            public void stateChanged(ChangeEvent e) {
                _button.setForeground(_colorChooser.getColor());
                _dropDown.hideWindow();
            }
        });
        _button = new JButton("Show JWindow");
        _button.setIcon(new MetalComboBoxIcon());
        _button.setHorizontalTextPosition(SwingConstants.LEFT);
        this.getContentPane().add(_button);
        _dropDown = new DropDownComponent2(DropDownFrame.this, _colorChooser, _button);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                DropDownFrame dropDownFrame = new DropDownFrame();
            }
        });
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top