How to implement oval GradientPaint?

前端 未结 2 1540
天命终不由人
天命终不由人 2020-12-10 19:49

We know that there are a class named RadialGradientPaint in Java and we can use it to have a gradient painting for circle.

But I want to have an oval (e

相关标签:
2条回答
  • 2020-12-10 20:26

    Use an AffineTransform when drawing the RadialGradientPaint. This would require a scale instance of the transform. It might end up looking something like this:

    OvalGradientPaint

    import java.awt.*;
    import java.awt.MultipleGradientPaint.CycleMethod;
    import java.awt.geom.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    
    public class OvalGradientPaint {
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
    
                @Override
                public void run() {
                    // the GUI as seen by the user (without frame)
                    JPanel gui = new JPanel(new BorderLayout());
                    gui.setBorder(new EmptyBorder(2, 3, 2, 3));
    
                    gui.add(new OvalGradientPaintSurface());
                    gui.setBackground(Color.WHITE);
    
                    JFrame f = new JFrame("Oval Gradient Paint");
                    f.add(gui);
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    // See http://stackoverflow.com/a/7143398/418556 for demo.
                    f.setLocationByPlatform(true);
    
                    // ensures the frame is the minimum size it needs to be
                    // in order display the components within it
                    f.pack();
                    // should be done last, to avoid flickering, moving,
                    // resizing artifacts.
                    f.setVisible(true);
                }
            };
            // Swing GUIs should be created and updated on the EDT
            // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
            SwingUtilities.invokeLater(r);
        }
    }
    
    class OvalGradientPaintSurface extends JPanel {
    
        public int yScale = 150;
        public int increment = 1;
        RadialGradientPaint paint;
        AffineTransform moveToOrigin;
    
        OvalGradientPaintSurface() {
            Point2D center = new Point2D.Float(100, 100);
            float radius = 90;
            float[] dist = {0.05f, .95f};
            Color[] colors = {Color.RED, Color.MAGENTA.darker()};
            paint = new RadialGradientPaint(center, radius, dist, colors,CycleMethod.REFLECT);
            moveToOrigin = AffineTransform.
                    getTranslateInstance(-100d, -100d);
            ActionListener listener = new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent ae) {
                    if (increment < 0) {
                        increment = (yScale < 50 ? -increment : increment);
                    } else {
                        increment = (yScale > 150 ? -increment : increment);
                    }
                    yScale += increment;
                    repaint();
                }
            };
    
            Timer t = new Timer(15, listener);
            t.start();
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            AffineTransform moveToCenter = AffineTransform.
                    getTranslateInstance(getWidth()/2d, getHeight()/2d);
            g2.setPaint(paint);
            double y = yScale/100d;
            double x = 1/y;
            AffineTransform at = AffineTransform.getScaleInstance(x, y);
    
            // We need to move it to the origin, scale, and move back.
            // Counterintutitively perhaps, we concatentate 'in reverse'.
            moveToCenter.concatenate(at);
            moveToCenter.concatenate(moveToOrigin);
            g2.setTransform(moveToCenter);
    
            // fudge factor of 3 here, to ensure the scaling of the transform
            // does not leave edges unpainted.
            g2.fillRect(-getWidth(), -getHeight(), getWidth()*3, getHeight()*3);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 200);
        }
    }
    

    Original image: The original static (boring) 'screen shot' of the app.

    OvalGradientPaint

    0 讨论(0)
  • 2020-12-10 20:29

    RadialGradientPaint provides two ways to paint itself as an ellipse instead of a circle:

    1. Upon construction, you can specify a transform for the gradient. For example, if you provide the following transform: AffineTransform.getScaleInstance(0.5, 1), your gradient will be an upright oval (the x dimension will be half that of the y dimension).

    2. Or, you can use the constructor that requires a Rectangle2D be provided. An appropriate transform will be created to make the gradient ellipse bounds match that of the provided rectangle. I found the class documentation helpful: RadialGradientPaint API. In particular, see the documentation for this constructor.

    0 讨论(0)
提交回复
热议问题