0

This is probably an elementary question. However, I have completed reading the 9th Chapter of Java Programming for the Absolute Beginner and have approached the Challenges section. I cannot quite get the progam to show a gradient from dark to light.

The question asks:

"Create a Canvas that paints a gradient that's dark on one side and slowly gets lighter as it moves to the other side."

I have looked at the Java Challenge on Creating a Canvas page (which I asked about before) and got a better understanding of creating a color gradient canvas, however, I am still having great difficulty.

I think that my main problem is how to get the gray colors in between as the program shows a completely black square or when run with just the first for loop, a completely white square. I THINK THAT MY FOR LOOPS ARE PROBLEMATIC AND DO NOT CORRECTLY IDENTIFY THE VARIABLES.

An answer to this question can potentially aid many new Java programmers in understanding Graphics and Canvas.

I do not know JFrame, Swing, Points, JPanels, BufferedImage, or GradientPaint.

Thank you very much for your time and cooperation reagrding this matter.

HERE IS THE CODE:

import java.awt.*;

public class RandomColorSquare extends GUIFrame {
    Canvas slight;
    public final static int MIN = 0,
        MAX = 225;

    public RandomColorSquare(int r, int g, int b) {
        super("Random Color Square");
        r = r >= MIN && r <= MAX ? r : MIN;
        g = g >= MIN && g <= MAX ? g : MIN;
        b = r >= MIN && b <= MAX ? b : MIN;
        slight = new Canvas();
        slight.setBackground(new Color(r,g, b));
        slight.setSize(200, 150);
        add(slight, BorderLayout.CENTER);

        for(r=0; r<225; r++) {
            Color c = slight.getBackground().brighter();
            slight.setBackground(c);
        }

        for (g=0; g<225; g++) {
            Color d = slight.getBackground().darker();
            slight.setBackground(d);
        }
        for (b=0; b<225; b++) {
             Color e = slight.getBackground().darker();
             slight.setBackground(e);
        }

        pack();
        setVisible(true);
    }

    public static void main(String args[]) {
        if (args.length != 3) {
            new RandomColorSquare(0, 0, 0);
        }
        else {
            new RandomColorSquare(Integer.parseInt(args[0]),                                     Integer.parseInt(args[1]),
                   Integer.parseInt(args[2]));
        }
    }
}
Community
  • 1
  • 1
  • 1
    *"I do not know JFrame, Swing, Points, JPanels, or GradientPaint"* Guess what, it might be time to learn ;) – MadProgrammer Dec 31 '12 at 00:05
  • That could be true, however, I'm trying to ensure I understand the material covered in the book. I feel that the author of the book was obviously trying to check if the reader (me) understood something else if I have not learned that, however I am still supposed to be able to write the program. Basically, something I already know (not including GradientPaint, etc.) is supposed to allow me to answer the question. –  Dec 31 '12 at 00:07
  • If you set a background color twice, that doesn't add both colors to the background. It only uses the last color. So what your code does is keep changing the background color until it reaches the final loop. And in that loop, you keep changing the color until it's black. – aly Dec 31 '12 at 01:33
  • How can I add the colors together? –  Dec 31 '12 at 01:56

2 Answers2

4

First of all, as I mentioned in the comment, when you setBackground you are changing the background of the Canvas, not adding to it. So whatever you set it to last is what you see. In your case, that is the darkest form of blue, which is just black. If you comment out the last two loops, you get a white background (the brightest red).

However. Using only what you know this is the best I can come up with. It involves creating your own custom Canvas, which I called CustomCanvas. In there, you can override the paint method and keep drawing progressively lighter filled rectangles across the screen. Here's a small sample to help you understand what I mean:

class CustomeCanvas extends Canvas{
    public void paint(Graphics g){
        Color background = new Color(30,30,120); //Set this accordingly
        for(int i=0;i<getWidth();i++){
            g.setColor(background);
            background = getBrighter(background);
            g.fillRect(i,0, 1, getHeight());
        }
    }

    private Color getBrighter(Color c) {
        int r = c.getRed();
        int g = c.getGreen();
        int b = c.getBlue();

        if(r< MAX) r+=1;
        if(g< MAX) g+=1;
        if(b< MAX) b+=1;

        return new Color(r,g,b);
    }
}

Which produces this background:

enter image description here

I still recommend reading about GradientPaint which makes this process a lot easier and nicer.

aly
  • 523
  • 2
  • 7
3

You can override paint() in your Canvas in a manner similar to how this example does for Panel. In your implementation, use drawImage() to render a BufferedImage in which you've used setRGB() to construct your gradient.

Addendum: The example below illustrates the approach by creating a random image. You can create a gradient similarly.

image]

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/** @see https://stackoverflow.com/a/14096121/230513 */
public class AWTImage {

    public static void main(String[] args) throws IOException {
        Frame frame = new Frame();
        frame.add(new ImageCanvas());
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        frame.pack();
        frame.setVisible(true);
    }

    private static class ImageCanvas extends Canvas {

        private static final Random r = new Random();
        private BufferedImage image;

        public ImageCanvas() {
            image = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
            for (int row = 0; row < image.getHeight(); row++) {
                for (int col = 0; col < image.getWidth(); col++) {
                    image.setRGB(col, row, r.nextInt());
                }
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        public void paint(Graphics g) {
            g.drawImage(image, 0, 0, this);
        }
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I sincerely appreciate your help, however, I have not yet learned BufferedImage in my text. Sorry to bother you again :( –  Dec 31 '12 at 00:25
  • I've implemented the approach above for a related task. – trashgod Dec 31 '12 at 00:48
  • You are awesome! However, I did not learn BufferedImage. I made an edit to my program and it is still not running. My for loops probably are wrong among other items. Is there any other way to answer this question? –  Dec 31 '12 at 01:14
  • @aly: shows an alternate approach. I you code, note that `brighter()` and `darker()` are _much_ bigger steps than you want. – trashgod Dec 31 '12 at 03:24