Java 使用arc2d旋转图形

Java 使用arc2d旋转图形,java,graphics,paint,graphics2d,Java,Graphics,Paint,Graphics2d,我正在尝试做一个轮盘赌赌场游戏,因此为此,我使用Arc2D软件包制作了我的轮盘赌 下面是我的代码 package roulette; import javax.swing.*; import java.awt.*; import java.awt.geom.Arc2D; import java.awt.geom.AffineTransform; import javax.swing.Timer; import java.awt.event.ActionEvent; import java.awt

我正在尝试做一个轮盘赌赌场游戏,因此为此,我使用Arc2D软件包制作了我的轮盘赌

下面是我的代码

package roulette;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Arc2D;
import java.awt.geom.AffineTransform;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class RouletteInterface extends JPanel{
    public int spinValue = 0;
    public void paint(Graphics g){       
        Graphics2D g2d = (Graphics2D)g;
        paintRoulette(g2d);

    }

    public void paintRoulette(Graphics2D g2d) {
        RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHints(hints);
        AffineTransform at = AffineTransform.getTranslateInstance(10, 10);
        at.rotate(spinValue, 10, 10);


        double angle = 360 / 36.9;
        double startAngle = 0;
        int color = 0;
        for(int i = 0; i < 37; i++) {
            if(i == 0) {
                g2d.setColor(Color.GREEN);
            } else {
                if(color == 0) {
                    g2d.setColor(Color.BLACK);
                    color = 1;
                } else {
                    g2d.setColor(Color.RED);
                    color = 0;
                }
            }

            g2d.fill(new Arc2D.Double(100, 100, 300, 300, startAngle, angle, Arc2D.PIE));
            startAngle += angle;
        }

        g2d.transform(at);

        Timer timer = new Timer(5, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                spinValue += 0.01;
                repaint();
            }
        });
        timer.start();
    }
}
打包轮盘赌;
导入javax.swing.*;
导入java.awt.*;
导入java.awt.geom.Arc2D;
导入java.awt.geom.AffineTransform;
导入javax.swing.Timer;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
公共类轮盘赌界面扩展JPanel{
公共值=0;
公共空间绘制(图形g){
Graphics2D g2d=(Graphics2D)g;
彩轮盘赌(g2d);
}
公共虚空彩轮盘(Graphics2D g2d){
RenderingHists=new RenderingHists(RenderingHists.KEY\u ANTIALIASING,RenderingHists.VALUE\u ANTIALIAS\u ON);
g2d.setRenderingHints(提示);
AffineTransform at=AffineTransform.getTranslateInstance(10,10);
旋转(旋转值,10,10);
双角度=360/36.9;
双星缠结=0;
int color=0;
对于(int i=0;i<37;i++){
如果(i==0){
g2d.setColor(Color.GREEN);
}否则{
如果(颜色==0){
g2d.setColor(Color.BLACK);
颜色=1;
}否则{
g2d.setColor(Color.RED);
颜色=0;
}
}
g2d.fill(新的Arc2D.Double(100100300300,startAngle,angle,Arc2D.PIE));
startAngle+=角度;
}
g2d.变换(at);
计时器计时器=新计时器(5,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
spinValue+=0.01;
重新油漆();
}
});
timer.start();
}
}
简言之,我没有使用generalpath,因为我希望像原始轮盘赌一样用红色/绿色或黑色填充每个弧,对于旋转,我尝试使用计时器增加AfinneTransformation的spinValue(这对我有效,但当我使用generalpath时),但是当我运行代码时,什么也没有发生。它只显示没有动画的轮盘赌。我能做什么


提前感谢。

绘画和图形通常都是非常高级的主题,Java/Swing很好地将API“通用化”为易于使用的内容,但仍然需要花费时间和精力来全面学习和理解

我强烈建议对预订的javadoc进行标记,因为您将定期返回到它们(我仍然这样做)

有很多问题,这些问题使你的生活更加困难

public void paint(Graphics g){       
    Graphics2D g2d = (Graphics2D)g;
    paintRoulette(g2d);

}
您应该支持覆盖
paintComponent
而不是
paint
,绘制是一个复杂的过程,您需要仔细选择进入的入口点。此外,您应该始终调用paint方法
super
方法,除非您完全、积极地准备好自己接管它的核心功能

在您的情况下,在将
图形
上下文传递给
paintroulete
之前,您还应该制作一份
图形
上下文的副本,因为
图形
是一个共享资源,您正在应用的转换将导致在组件之后绘制的任何内容出现问题

转换

AffineTransform at = AffineTransform.getTranslateInstance(10, 10);
at.rotate(spinValue, 10, 10);
这有点有趣。您正在创建
10x10
的翻译,这将移动
图形
上下文的原点。然后应用一个定位到
10x10
的旋转

我提到它的原因是因为你当时

g2d.fill(new Arc2D.Double(100, 100, 300, 300, startAngle, angle, Arc2D.PIE));
这意味着圆弧从组件的角部(添加平移)偏移
110x110
,并且您将围绕组件的上/左角(添加平移)的点
20x20
。。。这对我来说很奇怪,因为车轮的中心实际上位于
250x250
(从部件的左上角开始),这将产生一种非常奇怪的效果

最后,在绘制完成后应用转换,然后在绘制方法内部创建一个
计时器

绘画是连续进行的。因此,一个操作将影响下一个操作,这意味着您需要在绘制某些东西(您希望转换的东西)之前应用转换

您还需要了解,您不控制绘制过程,这意味着您的组件可能会在任何时候出于任何原因绘制,而无需您的交互。这意味着您可以在很短的时间内使用无限多的
计时器

相反,应该从
绘制过程外部控制计时器

另一件花了我一些时间的事情是

public int spinValue = 0;
//...
Timer timer = new Timer(5, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        spinValue += 0.01;
        repaint();
    }
});
您将
spinValue
声明为
int
,但要向其添加浮点值,这将导致小数部分被截断,因此该值将始终为
0

此外,
AffineTransform#rotate
要求角度以弧度为单位,而不是度。不确定这是否重要,但你应该意识到这一点

可运行的示例。。。 好的,在应用上面的代码之后,代码“可能”看起来像

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.AffineTransform;
import java.awt.geom.Arc2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new RoulettePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class RoulettePane extends JPanel {

        private double spinValue = 0;
        private Timer timer;

        public RoulettePane() {
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    spin();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            paintRoulette(g2d);
            g2d.dispose();
        }

        protected void spin() {
            if (timer != null && timer.isRunning()) {
                return;
            }
            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    spinValue += 0.01;
                    repaint();
                }
            });
            timer.start();
        }

        protected void paintRoulette(Graphics2D g2d) {
            RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHints(hints);

            int width = getWidth();
            int height = getHeight();

            int dimeter = Math.min(width, height);

            AffineTransform at = AffineTransform.getRotateInstance(spinValue, dimeter / 2, dimeter / 2);
            g2d.transform(at);

            double angle = 360 / 36.9;
            double startAngle = 0;
            int color = 0;
            for (int i = 0; i < 37; i++) {
                if (i == 0) {
                    g2d.setColor(Color.GREEN);
                } else {
                    if (color == 0) {
                        g2d.setColor(Color.BLACK);
                        color = 1;
                    } else {
                        g2d.setColor(Color.RED);
                        color = 0;
                    }
                }

                g2d.fill(new Arc2D.Double(0, 0, dimeter, dimeter, startAngle, angle, Arc2D.PIE));
                startAngle += angle;
            }
        }
    }
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.geom.AffineTransform;
导入java.awt.geom.Arc2D;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公共空间