I have the following code to draw a RadialGradientPaint circle:
public class Character {
public static void draw(Graphics2D g2d){
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, 1000, 750);
drawVisibilityPolygon(g2d);
}
private static void drawVisibilityPolygon(Graphics2D g2d){
Point center = new Point(1000 / 2, 750 / 2);
float radius = 200;
float[] dist = {
0f,
1f
};
Color[] colors = {
new Color(0, 0, 0, 0),
new Color(0, 0, 0, 255)
};
drawGradientCircle(g2d, radius, dist, colors, center);
}
private static void drawGradientCircle(Graphics2D g2d, float radius, float[] dist, Color[] colors, Point2D center){
RadialGradientPaint rgp = new RadialGradientPaint(center, radius, dist, colors);
g2d.setPaint(rgp);
g2d.fill(new Ellipse2D.Double(center.getX() - radius, center.getY() - radius, radius * 2, radius * 2));
}
}
The draw method is called by the Display class:
public class Display extends JPanel {
#Override
public void paintComponent(Graphics g){
// SETUP
BufferedImage base = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = base.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, getWidth(), getHeight());
// DRAW STUFF
Character.draw(g2d);
// FINISH UP
g.drawImage(base, 0, 0, null);
g2d.dispose();
g.dispose();
}
}
The display class is contained in a JFrame:
public class Window extends JFrame {
private Display display = new Display();
public Window(String title, int width, int height){
super(title);
add(display);
setSize(width, height);
setIgnoreRepaint(false);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public Display getDisplay() {
return display;
}
}
This works fine, but I want to fill the part outside of the circle (and only that part) with a color.
I've tried using an AlphaComposite but I cant figure out how to use it to do this. I could just make a bigger circle and decrease the dist1 value but that takes too long to draw (around 10ms on my machine as opposed to the 2ms of the circle in the image). I'm trying to put this into a game.
How would I go about this? Thanks in advance and sorry if this has an obvious solution but I just can't put my finger on it.
If you need more information just ask.
Painting with non-opaque colors causes background to show, so you have to set the background, so you have to set the appropriate background. Have a look at this demo :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
public class APanel extends JPanel{
APanel(){
setPreferredSize(new Dimension(600,600));
setBackground(Color.YELLOW);
setBorder(new TitledBorder(new LineBorder(new Color(169, 169, 169)),
"Gradient Circle", TitledBorder.LEADING, TitledBorder.BELOW_TOP, null, null));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw((Graphics2D) g);
}
public static void draw(Graphics2D g2d){
g2d.setColor(Color.RED);
g2d.fillRect(100,100, 400, 400);
drawVisibilityCircle(g2d);
}
private static void drawVisibilityCircle(Graphics2D g2d){
Point center = new Point(300, 300);
float radius = 200;
float[] dist = { 0f, 1f};
Color[] colors = { new Color(0, 0, 0, 0), new Color(0, 0, 0, 255)};
//workaround to prevent background color from showing
drawBackGroundCircle(g2d, radius, Color.WHITE, center);
drawGradientCircle(g2d, radius, dist, colors, center);
}
private static void drawBackGroundCircle(Graphics2D g2d, float radius, Color color, Point2D center){
g2d.setColor(color);
radius -= 1;//make radius a bit smaller to prevent fuzzy edge
g2d.fill(new Ellipse2D.Double(center.getX() - radius, center.getY()
- radius, radius * 2, radius * 2));
}
private static void drawGradientCircle(Graphics2D g2d, float radius, float[] dist, Color[] colors, Point2D center){
RadialGradientPaint rgp = new RadialGradientPaint(center, radius, dist, colors);
g2d.setPaint(rgp);
g2d.fill(new Ellipse2D.Double(center.getX() - radius, center.getY() - radius, radius * 2, radius * 2));
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
JPanel panel = new APanel();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Related
The BufferedImage drawn by the drawImage and clip method of Java Graphics2D have jagged edges, how to apply antialiasing?
The code:
BufferedImage img = ImageIO.read(new File("D:\\Pictures\\U\\U\\3306231465660486.jpg"));
JFrame frame = new JFrame();
frame.add(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
g2d.drawLine(10, 10, 300, 100);
g2d.translate(50, 200);
g2d.rotate(Math.toRadians(30), getWidth() / 2.0, getHeight() / 2.0);
g2d.drawImage(img, 0, 0, this);
g2d.clip(new Rectangle(-110, 110, 80, 110));
g2d.fill(new Rectangle(-100, 100, 100, 100));
}
});
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
One solution is to blur the border of the image once you load it. You should also use the RenderingHints.KEY_RENDERING with RenderingHints.VALUE_RENDER_QUALITY.
This is the final result:
The full code is available below. Note that is uses a blur method described by Marco13 in this answer: https://stackoverflow.com/a/22744303/4289700.
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint;
import java.awt.RadialGradientPaint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Main {
private static BufferedImage blurImageBorder(BufferedImage input, double border) {
int w = input.getWidth();
int h = input.getHeight();
BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = output.createGraphics();
g.drawImage(input, 0, 0, null);
g.setComposite(AlphaComposite.DstOut);
Color c0 = new Color(0x000000FF);
// Left
g.setPaint(new GradientPaint(new Point2D.Double(0, border), c0, new Point2D.Double(border, border), c0));
g.fill(new Rectangle2D.Double(0, border, border, h- border - border));
// Right
g.setPaint(new GradientPaint(new Point2D.Double(w - border, border), c0, new Point2D.Double(w, border), c0));
g.fill(new Rectangle2D.Double(w- border, border, border, h- border - border));
// Top
g.setPaint(new GradientPaint(new Point2D.Double(border, 0), c0, new Point2D.Double(border, border), c0));
g.fill(new Rectangle2D.Double(border, 0, w - border - border, border));
// Bottom
g.setPaint(new GradientPaint(new Point2D.Double(border, h - border), c0, new Point2D.Double(border, h), c0));
g.fill(new Rectangle2D.Double(border, h - border, w - border - border, border));
final float[] floatArray = new float[]{ 0, 1 };
final Color[] colorArray = new Color[]{ c0, c0 };
// Top Left
g.setPaint(new RadialGradientPaint(new Rectangle2D.Double(0, 0, border + border, border + border),
floatArray, colorArray, MultipleGradientPaint.CycleMethod.NO_CYCLE));
g.fill(new Rectangle2D.Double(0, 0, border, border));
// Top Right
g.setPaint(new RadialGradientPaint(
new Rectangle2D.Double(w - border - border, 0, border + border, border + border),
floatArray, colorArray, MultipleGradientPaint.CycleMethod.NO_CYCLE));
g.fill(new Rectangle2D.Double(w - border, 0, border, border));
// Bottom Left
g.setPaint(new RadialGradientPaint(
new Rectangle2D.Double(0, h - border - border, border + border, border + border),
floatArray, colorArray, MultipleGradientPaint.CycleMethod.NO_CYCLE));
g.fill(new Rectangle2D.Double(0, h - border, border, border));
// Bottom Right
g.setPaint(new RadialGradientPaint(
new Rectangle2D.Double(w - border - border, h - border - border, border + border, border + border),
floatArray, colorArray, MultipleGradientPaint.CycleMethod.NO_CYCLE));
g.fill(new Rectangle2D.Double(w - border, h - border, border, border));
g.dispose();
return output;
}
public static void main(String[] args) throws IOException {
BufferedImage raw = ImageIO.read(new File("/path/to/picture.jpg"));
BufferedImage img = blurImageBorder(raw, 1);
JFrame frame = new JFrame();
frame.add(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.drawLine(10, 10, 300, 100);
g2d.translate(50, 200);
g2d.rotate(Math.toRadians(30), getWidth() / 2.0, getHeight() / 2.0);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.drawImage(img, 0, 0, this);
g2d.fill(new Rectangle(-100, 100, 100, 100));
}
});
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
For the image, it is sufficient to paint the image into another image that is 2 pixels larger, and then draw the resulting image with bilinear interpolation. So you can just pass your image through a method like this one:
private static BufferedImage addBorder(BufferedImage image)
{
BufferedImage result = new BufferedImage(
image.getWidth() + 2, image.getHeight() + 2,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.drawImage(image, 1, 1, null);
g.dispose();
return result;
}
The result will be this:
Here is the MCVE, including the line that sets the ..._INTERPOLATION_BILINEAR rendering hint:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageBorderAntialiasing
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui()
{
//BufferedImage img = loadUnchecked("7bI1Y.jpg");
BufferedImage img = addBorder(loadUnchecked("7bI1Y.jpg"));
JFrame frame = new JFrame();
frame.add(new JPanel()
{
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setColor(Color.RED);
g2d.drawLine(10, 10, 300, 100);
g2d.translate(50, 200);
g2d.rotate(Math.toRadians(30),
getWidth() / 2.0, getHeight() / 2.0);
g2d.drawImage(img, 0, 0, this);
g2d.fill(new Rectangle(-100, 100, 100, 100));
}
});
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static BufferedImage addBorder(BufferedImage image)
{
BufferedImage result = new BufferedImage(
image.getWidth() + 2, image.getHeight() + 2,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.drawImage(image, 1, 1, null);
g.dispose();
return result;
}
private static BufferedImage loadUnchecked(String fileName)
{
try
{
return ImageIO.read(new File(fileName));
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
After this was answered, the question was updated to also ask about the clip method
Antialiasing the result of a clip operation may be more difficult. The clip operation is very hard "by nature" (and I assume that it eventually will be handled by something like a Stencil Buffer in hardware).
One approach to solve this could be do do the clipping manually. So instead of doing
g2d.clip(new Rectangle(-110, 110, 80, 110));
g2d.fill(new Rectangle(-100, 100, 100, 100));
you could do something like
Shape clip = new Rectangle(-110, 110, 80, 110);
Shape rectangleA = new Rectangle(-100, 100, 100, 100);
g2d.fill(clip(clip, rectangleA));
where the clip method is implemented to to manually compute the intersection of the shapes.
Note: Computing the intersection of two shapes can be rather expensive. If this becomes an issue, one might have to revise the approach. But on another note: I've heavily been doing Swing programming for ~20 years now, and cannot remember to ever have used the Graphics2D#clip method at all....
The difference between using Graphics2D#clip and the manual clipping is shown here:
and a closeup:
And there is the code:
(It does no longer contain the image part, because the problems are fairly unrelated...)
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ClippedDrawingAntialiasing
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui()
{
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new GridLayout(1,2));
frame.getContentPane().add(new JPanel()
{
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
g2d.drawLine(10, 10, 300, 100);
g2d.translate(50, 200);
g2d.rotate(Math.toRadians(30),
getWidth() / 2.0, getHeight() / 2.0);
g2d.clip(new Rectangle(-110, 110, 80, 110));
g2d.fill(new Rectangle(-100, 100, 100, 100));
g2d.setColor(Color.BLUE);
g2d.fill(new Rectangle(-60, 120, 60, 170));
}
});
frame.getContentPane().add(new JPanel()
{
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
g2d.drawLine(10, 10, 300, 100);
g2d.translate(50, 200);
g2d.rotate(Math.toRadians(30),
getWidth() / 2.0, getHeight() / 2.0);
Clipper clipper =
new Clipper(new Rectangle(-110, 110, 80, 110));
g2d.fill(clipper.clip(new Rectangle(-100, 100, 100, 100)));
g2d.setColor(Color.BLUE);
g2d.fill(clipper.clip(new Rectangle(-60, 120, 60, 170)));
}
});
frame.setSize(1200, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class Clipper
{
private final Shape shape;
Clipper(Shape shape)
{
this.shape = shape;
}
Shape clip(Shape other)
{
Area a = new Area(shape);
a.intersect(new Area(other));
return a;
}
}
}
So I am trying to draw an arc and put a circle around its round endpoint, but I am having issues due to rounding to the nearest pixel. This is visible in some but not all cases.
Is there a way to draw circles using floating points and anti-aliasing to eliminate this rounding error?
You can run this code to see the problem. I have drawn arcs of 0 length (appearing as large dots) instead of full arcs for clarity.
import java.awt.*;
import javax.swing.*;
public class Example extends JFrame {
private int CENTER = 200;
private static int WINDOW = 400;
private int LEFT = 50;
private int TOP = 50;
private int DIM = 300;
private int DIAMETER = 26;
public Example () {
super();
}
public void paint (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(16, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
g2.setColor(new Color(0, 0, 255));
g2.drawArc(LEFT, TOP, DIM, DIM, 0, 0);
g2.drawArc(LEFT, TOP, DIM, DIM, 32, 0);
g2.drawArc(LEFT, TOP, DIM, DIM, 115, 0);
g2.drawArc(LEFT, TOP, DIM, DIM, 200, 0);
g2.drawArc(LEFT, TOP, DIM, DIM, 331, 0);
this.drawCircle(g2, 0);
this.drawCircle(g2, 32);
this.drawCircle(g2, 115);
this.drawCircle(g2, 200);
this.drawCircle(g2, 331);
g2.setStroke(new BasicStroke(1));
g2.setColor(new Color(0, 0, 0));
g2.drawLine(0, CENTER, DIM * 2, CENTER);
g2.drawLine(CENTER, 0, CENTER, DIM * 2);
}
private void drawCircle(Graphics2D g, int angle) {
g.setStroke(new BasicStroke(3));
g.setColor(new Color(0, 0, 255));
g.drawOval(
Math.round(CENTER + (float)(Math.cos(Math.toRadians(angle)) * (DIM/2)) - DIAMETER/2),
Math.round(CENTER - (float)(Math.sin(Math.toRadians(angle)) * (DIM/2)) - DIAMETER/2),
DIAMETER,
DIAMETER
);
}
public static void main (String args[]) {
Example e = new Example();
e.setSize(WINDOW, WINDOW);
e.setVisible(true);
e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
As an alternative, consider Ellipse2D with suitable RenderingHints. Typical usage is shown here.
Ellipse2D circle = new Ellipse2D.Float(…);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHints(…);
g2d.fill(circle);
Because various RenderingHints are implementation dependent, the example below will let you evaluate the effects individually.
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/38669048/230513
*/
public class Test {
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JPanel() {
private static final int N = 8;
private final Ellipse2D ellipse = new Ellipse2D.Float();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
g2d.setStroke(new BasicStroke(N));
ellipse.setFrame(N, N, getWidth() - 2 * N, getHeight() - 2 * N);
g2d.draw(ellipse);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
});
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Test()::display);
}
}
I am working on a class that can rotate a wheel around the center. The wheel is created using graphics2d, but I can not figure out exactly how to get the wheel to rotate around the center.
Currently, the wheel rotates, but not exactly about the origin.
My ultimate goal here is to create the wheel so that it is multicolored as well as a program around it, but my main concern here is getting the rotating wheel to work. If you could point me in the right direction I would be forever grateful!
Here is my current code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class RotateApp {
private static final int N = 3;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(N, N, N, N));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new RotatePanel());
frame.pack();
frame.setVisible(true);
System.out.println();
}
});
}
}
class RotatePanel extends JPanel implements ActionListener {
private static final int SIZE = 256;
private static double DELTA_THETA = Math.PI / 90;
private final Timer timer = new Timer(25, this);
private Image image = RotatableImage.getImage(SIZE);
private double dt = DELTA_THETA;
private double theta;
public RotatePanel() {
this.setBackground(Color.lightGray);
this.setPreferredSize(new Dimension(
image.getWidth(null), image.getHeight(null)));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
image = RotatableImage.getImage(SIZE);
dt = -dt;
}
});
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
g2d.rotate(theta);
g2d.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
g2d.drawImage(image, 0, 0, null);
}
public void actionPerformed(ActionEvent e) {
theta += dt;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
class RotatableImage {
private static final Random r = new Random();
static public Image getImage(int size) {
BufferedImage bi = new BufferedImage(
size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1));
g2d.setStroke(new BasicStroke(10.0f));
g2d.draw(new Line2D.Double(0, 100, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 200, 100));
g2d.draw(new Line2D.Double(100, 0, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 100, 200));
g2d.draw(new Line2D.Double(25, 25, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 175, 175));
g2d.draw(new Line2D.Double(175, 25, 100, 100));
g2d.draw(new Line2D.Double(100, 100, 25, 175));
g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));
g2d.dispose();
return bi;
}
}
You can use the Rotated Icon class to do the rotation for you so you don't have to worry about all the rotation logic and the rotation logic is in a reusable class.
An example of using this class would be:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class Rotation4 extends JPanel
{
private JLabel label;
private RotatedIcon rotated;
private int degrees;
public Rotation4(Image image)
{
setLayout( new GridBagLayout() );
Icon icon = new ImageIcon( image );
rotated = new RotatedIcon(icon, 0);
rotated.setCircularIcon(true);
label = new JLabel(rotated);
label.setOpaque(true);
label.setBackground(Color.RED);
add(label, new GridBagConstraints());
setDegrees( 0 );
}
public void setDegrees(int degrees)
{
this.degrees = degrees;
rotated.setDegrees( degrees );
label.revalidate();
label.repaint();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
Image bi = RotatableImage.getImage(210);
final Rotation4 r = new Rotation4(bi);
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
r.setDegrees( value );
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(r));
f.add(slider, BorderLayout.SOUTH);
f.setSize(400, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
static class RotatableImage
{
private static final Random r = new Random();
static public Image getImage(int size)
{
BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1));
g2d.setStroke(new BasicStroke(10.0f));
g2d.draw(new Line2D.Double(5, 105, 205, 105));
g2d.draw(new Line2D.Double(105, 5, 105, 205));
g2d.draw(new Line2D.Double(35, 35, 175, 175));
g2d.draw(new Line2D.Double(175, 35, 35, 175));
g2d.draw(new Ellipse2D.Double(5, 5, 199, 199));
g2d.setColor(Color.BLACK);
g2d.fillOval(100, 100, 10, 10);
g2d.dispose();
return bi;
}
}
}
Note I also had to make changes with your image and your painting. These changes will need to be made whether you use the RotatedIcon or do the rotation code yourself:
The image size was changed to 210. This is because your stroke size is 10, so you need to account for the extra pixels in the circle outline.
You need to change the original of the circle by half the stroke size. So in this case the origin becomes (5, 5).
The size of the oval needs to be changed to 199. This is because of the way the outline of the oval is painted. 1 extra pixel is needed for the outline. If you leave the size at 200 then 1 pixel of the outline will be lost. This is not very noticeable when using a stroke size of 10, but if you use a size of 1, then the outline will be missing at the right and bottom edges.
The locations of your lines needs to be changes. you don't want the line right to the edge of the circle because then you will get a flat line at the edge instead of the rounded line. So I started the line 5 pixels from the start and ended it 5 pixels from the end.
Ok, with little modification and fewer "spokes", I got your wheel rotate centric (1.) and multicolor (2.):
UPDATE on 1.) To make centric rotation in your (original) code just chage SIZEto 200!
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class RotateApp {
private static final int N = 3;
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(N, N, N, N));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new RotatePanel());
frame.pack();
frame.setVisible(true);
System.out.println();
});
}
}
class RotatePanel extends JPanel implements ActionListener {
private static final int SIZE = 256;
private static final double DELTA_THETA = Math.PI / 90;
private final Timer timer = new Timer(25, this);
private Image image = RotatableImage.getImage(SIZE);
private double dt = DELTA_THETA;
private double theta;
public RotatePanel() {
this.setBackground(Color.lightGray);
this.setPreferredSize(new Dimension(SIZE, SIZE));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
dt = -dt;
image = RotatableImage.getImage(SIZE);
}
});
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.rotate(theta,128,128);
g2d.drawImage(image, 0, 0, null);
}
#Override
public void actionPerformed(ActionEvent e) {
theta += dt;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
class RotatableImage {
private static final Random r = new Random();
static public Image getImage(int size) {
BufferedImage bi = new BufferedImage(
size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
final Color c1 = Color.getHSBColor(r.nextFloat(), 1, 1);
final Color c2 = Color.getHSBColor(r.nextFloat(), 1, 1);
g2d.setPaint(c1);
g2d.setStroke(new BasicStroke(10.0f));
g2d.draw(new Line2D.Double(0, size/2, size, size/2));
g2d.setPaint(c2);
g2d.draw(new Line2D.Double(size/2, 0, size/2, size));
g2d.setPaint(c1);
g2d.draw(new Ellipse2D.Double(0, 0, size, size));
g2d.dispose();
return bi;
}
}
Explanation:
So the "wobble" in your solution came from the fact, that you sized the image and the container/panel 256x256, but "based" your wheel layout on 200x200 only. I fixed all dimensions, and drew a correct cross, the g2d.rotate(theta,128,128); (!) relates then to the center.
Multi-color(easy): You can invoke setPaint() between each shape! ;)
I'm attempting to develop an image editor in Java. Part of my Java image implementation of the image editor is to load an image and draw some shapes in addition to performing rotation, scaling, etc.
I'm using JLabel to load images but is there a way to draw and apply transformation on an image using JLabel? All of the examples I've found online used JPanel.
You really need to look at Java2D turorial. You should draw images on Graphics2D and also rotate and scale images on Graphics2D.
Don't use JLabel, because
J-* Components are heavy (although JLabel is light-weighted). You can add an icon to a JLabel, but generally, they are used in stable cases, which won't be changed
frequently and arbitrarily. Painting on a J-* component brings
too many changes on it.
If you add a great number of components, it will also reduce performance.
(Each component would paint itself in a separate Graphics object which belongs to
it and its container will paint them all and the layout also matters.)
Another drawback is it is sometimes very difficult even impossible to
do some manipulations on a component or on a couple of components together. For example, what if you want to add two pictures and group them? You need 2 JLabels, 1 JPanel (maybe). Then what if you want to draw a line across these two images and group them again?
Below are the basic steps:
override paint or paintComponent method of a component;
cast Graphics instance to Graphics2D;
set some rendering attributes of Graphics2D;
set transform (rotation, scale, etc.) of Graphics2D;
draw image on Graphics2D
A large variety of classes are used, such as Graphics2D, AffineTransform, RenderingHints, BufferedImage, Shape, etc. and even more methods. I can't describe everything here. Just read the Java2D tutorial. It gives you an overview of the APIs and tells you how to do these things.
I'm using JLabel to load images but is there away to draw and apply
transformation on an image using JLabel?
Not sure exactly what you mean.
But you can simply get the icon of the JLabel (which is the image being displayed) do what needs to be done on the icon which we converted to BufferedImage and than reapply the icon via setIcon(..).
Here is a short example hope it helps:
JLabel with icon/BufferedImage before rotating -45 degrees:
JLabel after icon was got, rotated and re applied via setIcon(...):
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Test {
private static JLabel imageLabel;
private static JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
imageLabel = new JLabel(new ImageIcon(createImage()));//set image of JLabel
panel.add(imageLabel);
frame.add(panel);
frame.pack();
frame.setVisible(true);
startImageChangeTimer();//creates a timer which will rotate image after 5 seconds
}
private void startImageChangeTimer() {
Timer timer = new Timer(5000, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
//get JLabel Icon and convert to BufferedImage
BufferedImage img = getBufferedImageOfIcon(imageLabel.getIcon(), imageLabel.getWidth(), imageLabel.getHeight());
//rotate the image
img = createTransformedImage(img, -45);
//change the labels image
imageLabel.setIcon(new ImageIcon(img));
frame.pack();//resize frame accrodingly
}
});
timer.setRepeats(false);
timer.start();
}
});
}
public static BufferedImage createImage() {
BufferedImage img = new BufferedImage(100, 50, BufferedImage.TRANSLUCENT);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("Calibri", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
String text = "Hello world";
int textWidth = fm.stringWidth(text);
g2d.drawString(text, (img.getWidth() / 2) - textWidth / 2, img.getHeight() / 2);
g2d.dispose();
return img;
}
public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int originalWidth = image.getWidth();
int originalHeight = image.getHeight();
int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
Graphics2D g2d = rotatedBI.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return rotatedBI;
}
}
Update:
I do tend to agree with #shuangwhywhy. Draw image to JPanel via paintComponent(Graphics g) thus you can simply resize the image and set it to the JPanel image (via getters and setters)and than call repaint() to show the changes.
Here is Simple Image Editor
/*Arpana*/
CPanel displayPanel;
JButton sharpenButton, blurringButton, edButton, resetButton;
public ConvolveApp()
super();
Container container = getContentPane();
displayPanel = new CPanel();
container.add(displayPanel);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
panel
.setBorder(new TitledBorder(
"Click a Button to Perform the Associated Operation and Reset..."));
sharpenButton = new JButton("Sharpen");
sharpenButton.addActionListener(new ButtonListener());
blurringButton = new JButton("Blur");
blurringButton.addActionListener(new ButtonListener());
edButton = new JButton("Edge Detect");
edButton.addActionListener(new ButtonListener());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ButtonListener());
panel.add(sharpenButton);
panel.add(blurringButton);
panel.add(edButton);
panel.add(resetButton);
container.add(BorderLayout.SOUTH, panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
setVisible(true);
public static void main(String arg[]) {
new ConvolveApp();
class ButtonListener implements ActionListener
public void actionPerformed(ActionEvent e)
JButton button = (JButton) e.getSource();
if (button.equals(sharpenButton))
displayPanel.sharpen();
displayPanel.repaint();
else if (button.equals(blurringButton))
displayPanel.blur();
displayPanel.repaint();
else if (button.equals(edButton))
displayPanel.edgeDetect();
displayPanel.repaint();
else if (button.equals(resetButton))
displayPanel.reset();
displayPanel.repaint();
class CPanel extends JLabel
Image displayImage;
BufferedImage biSrc;
BufferedImage biDest;
BufferedImage bi;
Graphics2D big;
CPanel()
setBackground(Color.black);
loadImage();
setSize(displayImage.getWidth(this), displayImage.getWidth(this));
createBufferedImages();
bi = biSrc;
public void loadImage()
displayImage = Toolkit.getDefaultToolkit().getImage("Arpana.jpg");
MediaTracker mt = new MediaTracker(this);
mt.addImage(displayImage, 1);
try
mt.waitForAll();
if (displayImage.getWidth(this) == -1)
System.out.println("No jpg file");
System.exit(0);
public void createBufferedImages()
biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
big = biSrc.createGraphics();
big.drawImage(displayImage, 0, 0, this);
biDest = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
public void sharpen()
float data[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
public void blur()
float data[] = { 0.0625f, 0.125f, 0.0625f, 0.125f, 0.25f, 0.125f,
0.0625f, 0.125f, 0.0625f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
public void edgeDetect()
float data[] = { 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
public void reset()
big.setColor(Color.black);
big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
big.drawImage(displayImage, 0, 0, this);
bi = biSrc;
public void update(Graphics g)
g.clearRect(0, 0, getWidth(), getHeight());
paintComponent(g);
I have only heard of people using JLabels to accomplish this. I recommend displaying the BufferedImage as the background of the JLabel. When the user applies an edit to the image, edit the image (If you don't already have a library for manipulating images, I strongly recommend imgscalr) and reapply it as the background of the JLabel (if it doesn't automatically update).
/* Arpana*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class ConvolveApp extends JFrame {
CPanel displayPanel;
JButton sharpenButton, blurringButton, edButton, resetButton;
public ConvolveApp() {
super();
Container container = getContentPane();
displayPanel = new CPanel();
container.add(displayPanel);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
panel
.setBorder(new TitledBorder(
"Click a Button to Perform the Associated Operation and Reset..."));
sharpenButton = new JButton("Sharpen");
sharpenButton.addActionListener(new ButtonListener());
blurringButton = new JButton("Blur");
blurringButton.addActionListener(new ButtonListener());
edButton = new JButton("Edge Detect");
edButton.addActionListener(new ButtonListener());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ButtonListener());
panel.add(sharpenButton);
panel.add(blurringButton);
panel.add(edButton);
panel.add(resetButton);
container.add(BorderLayout.SOUTH, panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
setVisible(true);
}
public static void main(String arg[]) {
new ConvolveApp();
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
if (button.equals(sharpenButton)) {
displayPanel.sharpen();
displayPanel.repaint();
} else if (button.equals(blurringButton)) {
displayPanel.blur();
displayPanel.repaint();
} else if (button.equals(edButton)) {
displayPanel.edgeDetect();
displayPanel.repaint();
} else if (button.equals(resetButton)) {
displayPanel.reset();
displayPanel.repaint();
}
}
}
}
class CPanel extends JLabel {
Image displayImage;
BufferedImage biSrc;
BufferedImage biDest; // Destination image is mandetory.
BufferedImage bi; // Only an additional reference.
Graphics2D big;
CPanel() {
setBackground(Color.black);
loadImage();
setSize(displayImage.getWidth(this), displayImage.getWidth(this));
createBufferedImages();
bi = biSrc;
}
public void loadImage() {
displayImage = Toolkit.getDefaultToolkit().getImage("Arpana.jpg");
MediaTracker mt = new MediaTracker(this);
mt.addImage(displayImage, 1);
try {
mt.waitForAll();
} catch (Exception e) {
System.out.println("Exception while loading.");
}
if (displayImage.getWidth(this) == -1) {
System.out.println("No jpg file");
System.exit(0);
}
}
public void createBufferedImages() {
biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
big = biSrc.createGraphics();
big.drawImage(displayImage, 0, 0, this);
biDest = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
}
public void sharpen() {
float data[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void blur() {
float data[] = { 0.0625f, 0.125f, 0.0625f, 0.125f, 0.25f, 0.125f,
0.0625f, 0.125f, 0.0625f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void edgeDetect() {
float data[] = { 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void reset() {
big.setColor(Color.black);
big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
big.drawImage(displayImage, 0, 0, this);
bi = biSrc;
}
public void update(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
paintComponent(g);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(bi, 0, 0, this);
}
}
I want to know how to make background gradient which is in another JPanel. Many articles found in internet,but all of them had demostrated how to overide the paintComponent() of the JPanel not how to do for a jPanel which is inside it.
I use Netbeans IDE. I created a new JPanel class and could overide its paintComponent(). I have another jpanel on it (dragged & dropped on to the parent JPanel). I want to make its background gradient.
Here is how I tried for parent. It worked. How can I overide this for child jpanel ?
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Color color1 = getBackground();
Color color2 = color1.darker();
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(
0, 0, color1,
0, h, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
If you are careful to invoke super.paintComponent(g), you can add the gradient directly to the panel as shown below.
For usability, I would resist the temptation to try making the individual components transparent. Note also that opacity is controlled by the Look & Feel.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* #see http://stackoverflow.com/q/12220853/230513
*/
public class GradientPanel extends JPanel {
private static final int N = 32;
public GradientPanel() {
this.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));
this.add(new JLabel("Test:", JLabel.CENTER));
this.add(new JTextField("This is a test."));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Color color1 = getBackground();
Color color2 = color1.darker();
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(
0, 0, color1, 0, h, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
private void display() {
JFrame f = new JFrame("GradientPanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new GradientPanel().display();
}
});
}
}
I think this is what you were trying to do
jPanel1 = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
int w = getWidth();
int h = getHeight();
Color color1 = new Color(81,80,106);
Color color2 = new Color(165,164,241);
GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
};