Java 如何实现椭圆形渐变绘制?

Java 如何实现椭圆形渐变绘制?,java,awt,graphics2d,affinetransform,radial-gradients,Java,Awt,Graphics2d,Affinetransform,Radial Gradients,我们知道Java中有一个名为RadialGradientPaint的类,我们可以使用它为圆绘制渐变 但是我想要一个椭圆形(GradientPaint)。如何实现椭圆形渐变绘制?在绘制径向渐变绘制时使用。这将需要变换的缩放实例。它可能最终看起来像这样: import java.awt.*; import java.awt.MultipleGradientPaint.CycleMethod; import java.awt.geom.*; import java.awt.event.*; impor

我们知道Java中有一个名为
RadialGradientPaint
的类,我们可以使用它为圆绘制渐变

但是我想要一个椭圆形(
GradientPaint
)。如何实现椭圆形
渐变绘制

在绘制
径向渐变绘制
时使用。这将需要变换的缩放实例。它可能最终看起来像这样:

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);
    }
}

import java.awt.*;
导入java.awt.MultipleGradientPaint.CycleMethod;
导入java.awt.geom.*;
导入java.awt.event.*;
导入javax.swing.*;
导入javax.swing.border.EmptyBorder;
公共级卵形镭射漆{
公共静态void main(字符串[]args){
Runnable r=新的Runnable(){
@凌驾
公开募捐{
//用户看到的GUI(无框架)
jpanelgui=newjpanel(newborderlayout());
setboorder(新的EmptyBorder(2,3,2,3));
添加(新的OvalGradientPaintSurface());
gui.setBackground(颜色:白色);
JFrame f=新JFrame(“椭圆形渐变漆”);
f、 添加(gui);
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//看http://stackoverflow.com/a/7143398/418556 用于演示。
f、 setLocationByPlatform(真);
//确保框架为所需的最小尺寸
//以便显示其中的组件
f、 包装();
//应最后完成,以避免闪烁、移动,
//调整工件大小。
f、 setVisible(真);
}
};
//应在EDT上创建和更新Swing GUI
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
类OvalGradientPaintSurface扩展了JPanel{
公共int yScale=150;
公共整数增量=1;
径向梯度涂料;
仿射变换运动原;
OvalGradientPaintSurface(){
Point2D中心=新的Point2D.Float(100100);
浮动半径=90;
float[]dist={0.05f、.95f};
Color[]colors={Color.RED,Color.MAGENTA.darker()};
paint=新的RadialGradientPaint(中心、半径、距离、颜色、循环方法反射);
moveToOrigin=仿射变换。
getTranslateInstance(-100d,-100d);
ActionListener=新建ActionListener(){
@凌驾
已执行的公共无效行动(行动事件ae){
如果(增量<0){
增量=(yScale<50?——增量:增量);
}否则{
增量=(yScale>150?——增量:增量);
}
yScale+=增量;
重新油漆();
}
};
定时器t=新定时器(15,侦听器);
t、 start();
}
@凌驾
公共组件(图形g){
超级组件(g);
图形2d g2=(图形2d)g;
AffineTransform moveToCenter=AffineTransform。
getTranslateInstance(getWidth()/2d,getHeight()/2d);
g2.设置油漆(油漆);
双y=yScale/100d;
双x=1/y;
AffineTransform at=AffineTransform.getScaleInstance(x,y);
//我们需要把它移到原点,缩放,然后向后移动。
//也许与直觉相反,我们认为“相反”。
moveToCenter.concatenate(at);
连接(moveToOrigin);
g2.setTransform(移动到中心);
//这里的模糊因子为3,以确保变换的缩放
//不会留下未上漆的边缘。
g2.fillRect(-getWidth(),-getHeight(),getWidth()*3,getHeight()*3);
}
@凌驾
公共维度getPreferredSize(){
返回新尺寸(500200);
}
}
原始图像:应用程序的原始静态(无聊的)“屏幕快照”


RadialGradientPaint
提供了两种将自身绘制为椭圆而不是圆的方法:

  • 构造时,可以为渐变指定变换。例如,如果提供以下变换:
    AffineTransform.getScaleInstance(0.5,1)
    ,则渐变将是一个直立的椭圆形(x维度将是y维度的一半)

  • 或者,您可以使用需要提供
    矩形2D
    的构造函数。将创建适当的变换,使渐变椭圆边界与所提供矩形的边界匹配。我发现类文档很有用:。有关详细信息,请参阅文档


  • @垃圾天啊,是的,这是我为Netbeans设计的“几乎是模板”(1)。我简直不能容忍为一个框架SSCCE做所有这些陈述而不发表一些评论。1) 除了复制粘贴文本和更改类名之外,还没有找到如何使用它。创建:
    Tools>Templates>Add
    ;编辑:
    工具>模板>在编辑器中打开
    ;用法:
    文件>新文件
    ,新模板应与添加到的类别相同;打开一个现有的元符号,例如${package}和
    ${name}
    @trashgood谢谢。现在使用元符号时效果更好。:)