我正在尝试做一个轮盘赌场游戏,所以为此我使用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();
}
}
简言之,我不使用generalpath,因为我想像原始轮盘一样用红色/绿色或黑色填充每个弧,对于旋转,我尝试使用计时器来增加AfinneTransformation的spinValue(这对我很有效,但当我使用generalpaath时),但当运行代码时,什么都没发生。它只向我展示了没有动画的轮盘赌。我能做什么?
提前谢谢。
绘画和图形通常是相当高级的主题,Java/Swing很好地将API"通用化"为易于使用的东西,但仍然需要时间和精力来学习和充分理解。
我强烈建议您在预订时标记"执行自定义绘画"、"AWT绘画"one_answers"Swing和2D Graphics绘画"以及"JavaDocs",因为您将定期(我仍然这样做)
有很多问题,这些问题会使你的生活变得困难。
从开始。。。
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D)g;
paintRoulette(g2d);
}
您应该支持覆盖paintComponent
而不是paint
,绘制是一个复杂的过程,您需要仔细选择进入的切入点。此外,您应该始终将绘制方法称为super
方法,除非您完全准备好自己接管其核心功能。
在您的情况下,在将Graphics
上下文传递给paintRoulette
之前,您还应该复制它,因为Graphics
是一个共享资源,您正在应用的转换将导致在组件之后绘制的任何内容出现问题。
转换。。。
AffineTransform at = AffineTransform.getTranslateInstance(10, 10);
at.rotate(spinValue, 10, 10);
这有点有趣。您正在创建10x10
的翻译,它将移动Graphics
上下文的原点。然后应用旋转,该旋转定位到10x10
。
我提到它的原因是因为你会…
g2d.fill(new Arc2D.Double(100, 100, 300, 300, startAngle, angle, Arc2D.PIE));
这意味着弧从组件的角偏移110x110
(在平移中添加),并且您将从组件的上/左角绕点20x20
旋转(在平移时添加)。。。这对我来说很奇怪,因为轮子的中心实际上在250x250
(从部件的上角/左角),这将产生一个非常奇怪的影响。
最后,在绘制完成后应用变换,然后在绘制方法内创建Timer
。。。
绘画是连续进行的。因此,一个操作将影响下一个操作,这意味着你需要在绘制(你想要转换的)之前应用转换
您还需要明白,您无法控制绘制过程,这意味着您的组件可能会在任何时候出于任何原因进行绘制,而无需进行交互。这意味着您可以在很短的时间内获得无限数量的Timer
。
相反,您的计时器应该通过paint
进程进行外部控制。
另一件事,我花了一些时间来解决是…
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;
}
}
}
}
nb:我暂时取消了翻译,因为我想专注于根据组件的实际宽度/高度使输出更加动态