Search code examples
javaswingpaintcomponentjcolorchooser

paintComponent() and JColorChooser


I am trying to write a program for class and I am stuck. I need to create a shape (my initial) and then fill it with it JColorChooser. I have been able to create my initial using paint, and graphics. Then I have been able to fill my shape by using g.setColor(new Color(11, 139, 198)); I don't know how to add a JColorChooser to this. This is my first post so let me know whatever I can do to make it easier to read. Here is my code:

/* Program - Letter 
 * Program Desc - 
 * Programmer - Bradon Fredrickson
 * Class - 
 * Created - Oct 1, 2014
 */
package letter;

import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Letter
{

    public static void PlainLetter()
    {
        /*
         * Creating GUI for letter
         */
        LetterDraw plainLetter = new LetterDraw();
        JFrame logo = new JFrame("My Logos");
        JLabel plain = new JLabel("Plain Letter");
        plain.setLocation(10, 0);
        plain.add(plainLetter);
        Container pane = logo.getContentPane();
        pane.setLayout(new GridLayout(1, 1));
        logo.setLocationRelativeTo(null); // Center the frame
        logo.add(plainLetter);
        logo.setVisible(true);
        logo.setSize(400, 200);
        logo.setLocation(400, 200);
        logo.setVisible(true);
        logo.setDefaultCloseOperation(logo.EXIT_ON_CLOSE);
    }//end plain letter

    public static void main(String[] args)
    {
        PlainLetter();
        new ColorChooser();
    }//end main method
}//end Letter

Second class - this is drawing my object

/* Program - ThirdLetter 
 * Program Desc - 
 * Programmer - Bradon Fredrickson
 * Class - 
 * Created - Oct 6, 2014
 */

package letter;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import javax.swing.JPanel;

public class LetterDraw extends JPanel
{

    /*
     * Creating my shape/letter
     */
    public void paint(Graphics graphics)
    {

        Path2D.Double path = new Path2D.Double();
        Graphics2D g = (Graphics2D) graphics;
        path.moveTo(17, 63);
        /*
         * Top Horizontal Line
         */
        path.curveTo(21, 60, 21, 43, 17, 37); //left vert
        path.curveTo(30, 43, 100, 43, 120, 37); //top horiz
        path.curveTo(115, 45, 115, 57, 117, 62); //right vert
        path.curveTo(105, 53, 60, 57, 17, 63); //bottom horiz right
        /*
         * Bottom Horizontal Line
         */
        path.moveTo(32, 97);
        path.curveTo(37, 85, 35, 79, 35, 77); //left vert
        path.curveTo(45, 79, 45, 79, 100, 79); //top left horiz
        path.curveTo(96, 85, 98, 92, 98, 98);//right vert
        path.curveTo(89, 93, 79, 94, 32, 97);//bottom right horiz
        /*
         * Vertical Line
         */
        path.moveTo(40, 130);
        path.curveTo(48, 110, 46, 70, 37, 55); //left vert
        path.curveTo(62, 55, 62, 55, 60, 55); //top horiz
        path.curveTo(68, 80, 68, 100, 63, 130); //right vert
        path.curveTo(60, 127, 50, 127, 40, 130);//bottom horiz
        g.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setStroke(new BasicStroke(3));
        //g.setStroke(new BasicStroke(4, BasicStroke.JOIN_BEVEL, 0));
        g.draw(path);
        g.setColor(new Color(11, 139, 198));
        g.fill(path);
    }//end paint
}//end LetterDraw

third - this is my colorChooser

/* Program - ColorChooser 
 * Program Desc - 
 * Programmer - Bradon Fredrickson
 * Class - 
 * Created - Oct 10, 2014
 */
package letter;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.colorchooser.ColorSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ColorChooser
{

    /**
     * Creating the color chooser
     */
    public ColorChooser()
    {
        JFrame frame = new JFrame("JColorChooser Popup");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JLabel label = new JLabel("www.java2s.com", JLabel.CENTER);
        label.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 48));

        frame.add(label, BorderLayout.NORTH);

        final JColorChooser colorChooser = new JColorChooser(label.
                getBackground());

        ColorSelectionModel model = colorChooser.getSelectionModel();
        ChangeListener changeListener = new ChangeListener()
        {
            public void stateChanged(ChangeEvent changeEvent)
            {
                Color newForegroundColor = colorChooser.getColor();
                label.setForeground(newForegroundColor);
            }
        };
        model.addChangeListener(changeListener);

        frame.add(colorChooser, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }//end colorChooser
}//end colorChooser class

Right now i get to 2 JFrames 1 for my shape and 1 for the JColorChooser. I would like to put them all in 1 frame also.


Solution

  • In your LetterDraw class, instead of doing

    g.setColor(new Color(11, 139, 198));
    

    better to have a class member Color color, and have a setter for it. Then do just do this

    public class LetterDraw extends JPanel {
        private Color color = Color.BLUE; // default;
    
        public void setColor(Color color) {
            this.color = color;
            repaint();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            ...
            g.setColor(color);
        }
    }
    

    Notice the paintComponent and super.paintComponent. See link from @trashgod in comments.

    As for the color selection, JColorChooser has a static method, from which you can call to show a color chooser dialog and obtain a returned color from. You can then use that color to call setColor on the LetterDraw. No need to create your own frame. For instance.

    Color color = JColorChooser.showDialog(null, "title", Color.BLUE);
    letterDraw.setColor(color);
    

    If you want to keep the color chooser frame open though and have the , using your current code, You would need to either use some kind of MVC/Observer design, or pass the instance of LetterDraw to the ColorChooser constructor, so that it can call LetterDraw's set color method, after it changes color.

    "I would like to put them all in 1 frame also"

    I just noticed that part of the question.

    You could forget that ColorChooser class all together and create the JColorChooser in the Letter class. So you have access to the LetterDraw object. Here's how a refactor might look

    import java.awt.BasicStroke;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GridBagLayout;
    import java.awt.RenderingHints;
    import java.awt.geom.Path2D;
    import javax.swing.JColorChooser;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    public class Letter {
    
        LetterDraw letterDraw = new LetterDraw();
    
        public Letter() {
            JFrame frame = new JFrame();
            JPanel letterDrawWrapper = new JPanel(new GridBagLayout());
            letterDrawWrapper.add(letterDraw);
            frame.add(letterDrawWrapper);
            frame.add(createColorChooser(), BorderLayout.PAGE_END);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        private JColorChooser createColorChooser() {
            JColorChooser colorChooser = new JColorChooser();
            colorChooser.getSelectionModel().addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    letterDraw.setColor(colorChooser.getColor());
                }
            });
            return colorChooser;
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new Letter();
                }
            });
        }
    }
    
    class LetterDraw extends JPanel {
    
        private Color color;
    
        public void setColor(Color color) {
            this.color = color;
            repaint();
        }
    
        @Override
        protected void paintComponent(Graphics graphics) {
            super.paintComponent(graphics);
            Path2D.Double path = new Path2D.Double();
            Graphics2D g = (Graphics2D) graphics;
            path.moveTo(17, 63);
            /*
             * Top Horizontal Line
             */
            path.curveTo(21, 60, 21, 43, 17, 37); //left vert
            path.curveTo(30, 43, 100, 43, 120, 37); //top horiz
            path.curveTo(115, 45, 115, 57, 117, 62); //right vert
            path.curveTo(105, 53, 60, 57, 17, 63); //bottom horiz right
                /*
             * Bottom Horizontal Line
             */
            path.moveTo(32, 97);
            path.curveTo(37, 85, 35, 79, 35, 77); //left vert
            path.curveTo(45, 79, 45, 79, 100, 79); //top left horiz
            path.curveTo(96, 85, 98, 92, 98, 98);//right vert
            path.curveTo(89, 93, 79, 94, 32, 97);//bottom right horiz
                /*
             * Vertical Line
             */
            path.moveTo(40, 130);
            path.curveTo(48, 110, 46, 70, 37, 55); //left vert
            path.curveTo(62, 55, 62, 55, 60, 55); //top horiz
            path.curveTo(68, 80, 68, 100, 63, 130); //right vert
            path.curveTo(60, 127, 50, 127, 40, 130);//bottom horiz
            g.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g.setStroke(new BasicStroke(3));
            //g.setStroke(new BasicStroke(4, BasicStroke.JOIN_BEVEL, 0));
            g.draw(path);
            g.setColor(color);
            g.fill(path);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(150, 150);
        }
    }