javacolorsjcolorchooser

How to override JColorChooser Reset Button?


In a previous post, I discussed overriding the Preview panel and all is working well, except a new question has come forth and hoping the fix for it is as easy.

This new question pertains to the Reset button. Based on the documentation, the Reset button will reset the Colors back to the original color that was passed in. This works great, but what if there is a secondary field?

Here is the code...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ColorChooserSample implements Runnable{

    public static void main(String args[]) {
        SwingUtilities.invokeLater(
                new ColorChooserSample());
    }

    private JPanel panel;
    JTextField counter;
    int vCounter = 1;

    @Override
    public void run() {
        JFrame frame = new JFrame(
                "JColorChooser Sample");
        frame.setDefaultCloseOperation(
                JFrame.EXIT_ON_CLOSE);

        panel = new JPanel();
        panel.setPreferredSize(new Dimension(300, 200));
        JButton button = new JButton(
                "Pick to Change JPanel Background");
        button.addActionListener(new ColorListener());
        panel.add(button);

        frame.add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public void setJPanelBackground(Color color) {
        panel.setBackground(color);
        panel.repaint();
    }

    public class ColorListener implements 
            ActionListener, ChangeListener {

        private JColorChooser chooser;

        private JPanel previewPanel;

        @Override
        public void actionPerformed(
                ActionEvent actionEvent) {
            Color backgroundColor = showDialog(panel, 
                    "Set JPanel Background", 
                    panel.getBackground());
            setJPanelBackground(backgroundColor);
        }

        private Color showDialog(Component component, 
                String title, Color initialColor) 
                        throws HeadlessException {
            chooser = new JColorChooser(initialColor);
            chooser.getSelectionModel()
                .addChangeListener(this);

            // configuring color chooser panel
            previewPanel = new JPanel();
            previewPanel.setBackground(initialColor);
            JLabel label = new JLabel("Hello World!");
            counter = new JTextField("0");
            previewPanel.add(label, BorderLayout.WEST);
            previewPanel.add(counter, BorderLayout.EAST);
            chooser.setPreviewPanel(previewPanel);

            // creating dialog
            ColorTracker ok = new ColorTracker(chooser);
            JDialog dialog = JColorChooser.createDialog(
                    component, title, true, chooser, 
                    ok, null);
            dialog.setVisible(true);
            return ok.getColor();
        }

        @Override
        public void stateChanged(ChangeEvent event) {
            Color newColor = chooser.getColor();
            previewPanel.setBackground(newColor);
            counter.setText(Integer.toString(vCounter++));
        }
    }

    private class ColorTracker implements ActionListener {

        private Color color;

        private JColorChooser chooser;

        public ColorTracker(JColorChooser chooser) {
            this.chooser = chooser;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            color = chooser.getColor();
        }

        public Color getColor() {
            return color;
        }

    }

}

The above code will first open this dialog.

enter image description here

Once the "Pick to Change JPanelBackground" button is clicked, it opens the JColorDialog with a modified Preview section. This section includes "Hello World" that will change background colors and a counter to count how many times the color has changed.

enter image description here

The following shows the last color selected but also shows 5 in the Textbox to signify that there were 5 color options clicked.

enter image description here

Click the reset button and the color background is set to the original, but the count was NOT reset back to 0.

enter image description here

You can pass in a Listener for both the OK and Cancel button but not the Reset button.

This is only an example, as there could be other items in the Preview section. The objective is how can the values other than Color be reset?


Solution

  • The only thing done by reset button is calling chooserPane.setColor(initialColor). So if what you really need is listening to color changes, you might do just that, by something like:

            chooser.getSelectionModel().addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    Color newColor = chooser.getColor();
                    previewPanel.setBackground(newColor);
                    counter.setText(Integer.toString(vCounter++));
                }
            });
    

    And your secondary panel gets updated.

    Having said that, if you really want to add a listener to the button, there's no exposed way of accessing it - you need to iterate the components all the way down until you find the button, and then add a listener to it.

    EDIT Alright, so it has to be the reset button. Since that's a local variable of some content creating method, it has to be removed surgically. Just change new JButton("abc") to your own button, with your own listener(s).

            Locale locale = dialog.getLocale();
            String resetString = UIManager.getString("ColorChooser.resetText", locale);
    
            Container contentPane = dialog.getContentPane();
            JPanel buttonPanel = null;
            for (Component c : contentPane.getComponents()) {
                if (c instanceof JPanel) {
                    buttonPanel = (JPanel) c;
                }
            }
    
            JButton resetButton = null;
            if (buttonPanel != null) {
                for (Component b : buttonPanel.getComponents()) {
                    if (b instanceof JButton) {
                        JButton button = (JButton) b;
                        if (resetString.equals(button.getText())) {
                            resetButton = button;
                            break;
                        }
                    }
                }
                if (resetButton != null) {
                    buttonPanel.remove(resetButton);
                    buttonPanel.add(new JButton("abc"));
                }
            }