TNT
TNT

Reputation: 2920

GradientPaint Working Strangely

While playing around with Java's painting tools, I came across the java.awt.GradientPaint class, which allows for gradient coloring when drawing shapes. I decided to play around with it, drawing filled-in rectangles with a red-to-green gradient on a JPanel, and immediately noticed something strange.

When I began drawing a rectangle, it was a solid red, and after I increased its height or width to a certain value, the gradient would appear. In some cases, the height or width of the rectangle had to be large (i.e. 200px) before the gradient showed up. Then I noticed that the closer to the right or the bottom of the JPanel that I began drawing the rectangle, the larger the size of the rectangle had to be before the gradient was applied. The GIF below should (hopefully) show what happens (the code used to create this example is further down):

Drawing gradient rectangles

So why does this occur? Is there a way to apply the gradient to the rectangles as soon as it is drawn?

(On a separate note, does anyone know of a way to restart the GIF animation after it shows the last frame?)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JPanel implements MouseListener, MouseMotionListener {
    int downX, downY, dragX, dragY;
    JComboBox combobox;
    String[] directions = {"Left-Right","Up-Down","Right-Left","Down-Up"};

    public Test() {
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        setPreferredSize(new Dimension(300,300));
        frame.add(this,BorderLayout.CENTER);

        combobox = new JComboBox(directions);
        frame.add(combobox,BorderLayout.NORTH);

        addMouseListener(this);
        addMouseMotionListener(this);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        if (combobox.getSelectedItem().equals(directions[0]))
            g2.setPaint(new GradientPaint(downX,downY,Color.red,dragX-downX,downY,Color.green));
        else if (combobox.getSelectedItem().equals(directions[1]))
            g2.setPaint(new GradientPaint(downX,downY,Color.red,downX,dragY-downY,Color.green));
        else if (combobox.getSelectedItem().equals(directions[2]))
            g2.setPaint(new GradientPaint(dragX-downX,downY,Color.red,downX,downY,Color.green));
        else if (combobox.getSelectedItem().equals(directions[3]))
            g2.setPaint(new GradientPaint(downX,dragY-downY,Color.red,downX,downY,Color.green));

        g2.fill(new Rectangle(downX,downY,dragX-downX,dragY-downY));
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }

    @Override
    public void mousePressed(MouseEvent ev) {
        downX = ev.getX();
        downY = ev.getY();
    }

    @Override
    public void mouseDragged(MouseEvent ev) {
        dragX = ev.getX();
        dragY = ev.getY();
        repaint();
    }

    @Override public void mouseClicked(MouseEvent ev) {} 
    @Override public void mouseEntered(MouseEvent ev) {}
    @Override public void mouseExited(MouseEvent ev) {}
    @Override public void mouseReleased(MouseEvent ev) {}
    @Override public void mouseMoved(MouseEvent ev) {}
}

Upvotes: 3

Views: 480

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347314

So, based on the JavaDocs

GradientPaint
public GradientPaint(float x1,
    float y1,
    Color color1,
    float x2,
    float y2,
    Color color2)

Constructs a simple acyclic GradientPaint object.

Parameters:
  x1 - x coordinate of the first specified Point in user space
  y1 - y coordinate of the first specified Point in user space
  color1 - Color at the first specified Point
  x2 - x coordinate of the second specified Point in user space
  y2 - y coordinate of the second specified Point in user space

  color2 - Color at the second specified Point

(emphasis added by me)

The x2 and y2 parameters are not width and height, but actual coordinates

This means that something like...

g2.setPaint(new GradientPaint(downX,downY,Color.red,dragX-downX,downY,Color.green));

should actually be...

g2.setPaint(new GradientPaint(downX, downY, Color.red, dragX, downY, Color.green));

Personally, I prefer to use something like LinearGradientPaint as it has more options, but's just me ;)

Upvotes: 3

Related Questions