如何在 Java 中创建 'cooldown rectangle' 效果?
How can I create a 'cooldown rectangle' effect in Java?
编辑:为了更具体一点,我想知道如何创建如图所示的超时效果。我知道绘制图像之类的,但我不了解超时效果背后的逻辑,因此出现了这个问题。
我一直在研究这个 'cooldown rectangle' 效果,它似乎可以在许多其他语言中实现,但到目前为止我还没有看到很多关于 Java 的解决方案。本质上我想创建一个函数来对图像产生这样的效果。
我已经知道叠加图像的基础知识,并且我遇到了一个 class,它可以做类似的事情,但在更广为人知的 'circular' 版本中。
我确实找到了 this tutorial,其中解释了如何使用 GameMaker 创建上述效果。但我不确定如何将这些知识转移到 Java。
如有任何帮助,我们将不胜感激。
那么,你需要的是...
- 一些加载图像的方法
- 一些绘制图像的方法
- 在图像上绘制超时效果的一些方法
- 一些定期更新UI的方法,计算剩余时间并更新UI
也许开始于:
- Reading/Loading an Image
- Painting in AWT and Swing and Performing Custom Painting
- 2D Graphics
- Concurrency in Swing and How to use Swing Timers
例如...
import java.awt.AlphaComposite;
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.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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TimeOutPane tp = new TimeOutPane();
tp.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
tp.executeTimeout();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TimeOutPane extends JPanel {
private BufferedImage background;
private float progress = 0;
private long startedAt;
private int timeout = 5000;
private Timer timer;
public TimeOutPane() throws IOException {
background = ImageIO.read(new File("/Volumes/Disk02/Dropbox/Ponies/url.png"));
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
public void setProgress(float progress) {
this.progress = progress;
repaint();
}
public float getProgress() {
return progress;
}
public void executeTimeout() {
if (timer == null) {
timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long diff = System.currentTimeMillis() - startedAt;
float progress = diff / (float) timeout;
if (diff >= timeout) {
progress = 1f;
timer.stop();
}
setProgress(progress);
}
});
} else if (timer.isRunning()) {
timer.stop();
}
startedAt = System.currentTimeMillis();
timer.start();
}
@Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
applyQualityRenderingHints(g2d);
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.setColor(Color.BLACK);
int radius = Math.max(getWidth(), getHeight()) / 2;
g2d.fillArc(-radius, -radius, radius * 4, radius * 4, 90, (int) (360f * (1f - progress)));
g2d.dispose();
}
}
public void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
}
}
编辑:为了更具体一点,我想知道如何创建如图所示的超时效果。我知道绘制图像之类的,但我不了解超时效果背后的逻辑,因此出现了这个问题。
我一直在研究这个 'cooldown rectangle' 效果,它似乎可以在许多其他语言中实现,但到目前为止我还没有看到很多关于 Java 的解决方案。本质上我想创建一个函数来对图像产生这样的效果。
我已经知道叠加图像的基础知识,并且我遇到了一个 class,它可以做类似的事情,但在更广为人知的 'circular' 版本中。
我确实找到了 this tutorial,其中解释了如何使用 GameMaker 创建上述效果。但我不确定如何将这些知识转移到 Java。
如有任何帮助,我们将不胜感激。
那么,你需要的是...
- 一些加载图像的方法
- 一些绘制图像的方法
- 在图像上绘制超时效果的一些方法
- 一些定期更新UI的方法,计算剩余时间并更新UI
也许开始于:
- Reading/Loading an Image
- Painting in AWT and Swing and Performing Custom Painting
- 2D Graphics
- Concurrency in Swing and How to use Swing Timers
例如...
import java.awt.AlphaComposite;
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.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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TimeOutPane tp = new TimeOutPane();
tp.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
tp.executeTimeout();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TimeOutPane extends JPanel {
private BufferedImage background;
private float progress = 0;
private long startedAt;
private int timeout = 5000;
private Timer timer;
public TimeOutPane() throws IOException {
background = ImageIO.read(new File("/Volumes/Disk02/Dropbox/Ponies/url.png"));
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
public void setProgress(float progress) {
this.progress = progress;
repaint();
}
public float getProgress() {
return progress;
}
public void executeTimeout() {
if (timer == null) {
timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long diff = System.currentTimeMillis() - startedAt;
float progress = diff / (float) timeout;
if (diff >= timeout) {
progress = 1f;
timer.stop();
}
setProgress(progress);
}
});
} else if (timer.isRunning()) {
timer.stop();
}
startedAt = System.currentTimeMillis();
timer.start();
}
@Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
applyQualityRenderingHints(g2d);
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.setColor(Color.BLACK);
int radius = Math.max(getWidth(), getHeight()) / 2;
g2d.fillArc(-radius, -radius, radius * 4, radius * 4, 90, (int) (360f * (1f - progress)));
g2d.dispose();
}
}
public void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
}
}