JColorChooser返回先前选择的颜色

时间:2016-03-28 08:23:44

标签: java jcolorchooser

我正在使用Java编写一个简单的绘图应用程序,当我选择一种颜色时,按钮背景会完美变化,但返回的颜色始终是前一种颜色。

例如,如果我选择黑色然后选择蓝色,它将涂成黑色。如果我在蓝色后选择另一种颜色,它将以蓝色绘制。

public class ColorChooserBtn extends JButton {

    private Color color;

    public ColorChooserBtn() {
        super();
        this.setBackground(Color.BLACK);
        this.setPreferredSize(new Dimension(16, 16));
        this.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                Color c = JColorChooser.showDialog(null, "Choose a Color", color);
                if (c != null){
                    setSelectedColor(c);
                    setBackground(color);
                }

           }
       });
    }
    public Color getSelectedColor() {
        return color;
    }

    public void setSelectedColor(Color newColor) {
        color = newColor;
    }

}

public class Paint {
DrawArea drawArea;
JButton  clearBtn;
ColorChooserBtn colorBtn;
ActionListener actionListener = new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == clearBtn){
            drawArea.clear();
        } else if(e.getSource() == colorBtn){
            drawArea.coloring(colorBtn.getSelectedColor());
        }

    }
};

public Paint() {
    JFrame frame =  new JFrame("Paint");
    frame.getContentPane().setLayout(new BorderLayout());
    drawArea = new DrawArea();
    frame.getContentPane().add(drawArea, BorderLayout.CENTER);
    JPanel controls = new JPanel();
    clearBtn = new JButton("Clear");
    clearBtn.addActionListener(actionListener);
    colorBtn =  new ColorChooserBtn();
    colorBtn.addActionListener(actionListener);

    controls.add(clearBtn);
    controls.add(colorBtn);

    frame.getContentPane().add(controls,BorderLayout.NORTH);
    frame.setSize(600, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}
public static void main(String[] args) {

    new Paint();

}

}

1 个答案:

答案 0 :(得分:1)

问题是通知ActionListener的顺序。通常,Swing调用以LIFO顺序监听

因此,使用以下代码,以及一些额外的System.out s ...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            ColorChooserBtn btn = new ColorChooserBtn();
            add(btn);
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Get color");
                    System.out.println(btn.getSelectedColor());
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class ColorChooserBtn extends JButton {

        private Color color;

        public ColorChooserBtn() {
            super();
            this.setBackground(Color.BLACK);
            this.setPreferredSize(new Dimension(16, 16));
            this.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Choose color");
                    Color c = JColorChooser.showDialog(null, "Choose a Color", color);
                    if (c != null) {
                        setSelectedColor(c);
                        setBackground(color);
                    }
                }
            });
        }

        public Color getSelectedColor() {
            return color;
        }

        public void setSelectedColor(Color newColor) {
            color = newColor;
        }

    }
}

...打印

Get color
null
Choose color

这意味着,在用于实际选择颜色的ActionListener之前,首先调用用于“获取”按钮中所选颜色的ActionListener

一种可能的解决方案可能是使用PropertyChangeListener并在更改propertyChanged时触发selectedColor事件,例如......

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            ColorChooserBtn btn = new ColorChooserBtn();
            add(btn);
            btn.addPropertyChangeListener("selectedColor", new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    System.out.println("Changed");
                    System.out.println(evt.getNewValue());
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class ColorChooserBtn extends JButton {

        private Color color;

        public ColorChooserBtn() {
            super();
            this.setBackground(Color.BLACK);
            this.setPreferredSize(new Dimension(16, 16));
            this.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Choose color");
                    Color c = JColorChooser.showDialog(null, "Choose a Color", color);
                    if (c != null) {
                        setSelectedColor(c);
                        setBackground(color);
                    }
                }
            });
        }

        public Color getSelectedColor() {
            return color;
        }

        public void setSelectedColor(Color newColor) {
            if (newColor != color) {
                Color oldColor = color;
                color = newColor;
                firePropertyChange("selectedColor", oldColor, newColor);
            }
        }

    }
}