java - Java Swing:通过鼠标点击 JPanel 制作一个不断增长的圆圈
问题描述
我是 Java 的初学者,这次我试图通过查找代码示例并编辑它们来了解更多信息,例如从这个网站。我有一个 JFrame,每次单击它(或更准确地说是其中的 JPanel)时,都会绘制一个圆圈,该圆圈会像水波纹一样向外增长/扩展。每个圆都以一定的半径开始,当达到更大的半径时将被删除或重新绘制(我选择半径“r”从 10 到 200)。我有两个程序几乎可以工作,但缺少一些东西。如果我是正确的,我可能也知道他们的问题是什么,但我不知道如何解决它们:
一个会生成不断增长的圆圈,但无论何时生成,它们都具有相同的大小,因为我不知道如何将半径分配给单个圆圈。代码改编自这里:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
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.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Ripples extends JPanel implements ActionListener{
public int r = 10;
private ArrayList<Point> p;
public Ripples() {
p = new ArrayList<>();
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getX(), e.getY()));
}
});
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.CYAN);
for (Point pt : p) {
g2.drawOval(pt.x-r, pt.y-r, 2*r, 2*r);
}
}
@Override
public void actionPerformed(ActionEvent evt) {
if(r<200){
r++;
} else {
r = 10;
}
repaint();
}
public static void Gui() {
JFrame f = new JFrame();
Ripples p = new Ripples();
p.setBackground(Color.WHITE);
f.setContentPane(p);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,300);
f.setVisible(true);
Timer t = new Timer(20,p);
t.start();
}
public static void main(String[] args) {
Gui();
}
}
另一个程序(我忘记了我从哪里得到它)具有不同半径的圆圈,具体取决于它们的生成时间,但是圆圈“闪烁”,因为-据我所知-它们都是同时处理的,因为代码不包含一个数组来单独存储和更新每个圆圈,就像上面的那样:
import java.awt.Color;
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.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Ripples extends JPanel {
int x,y;
int r = 10;
public Ripples(int x, int y) {
this.x = x;
this.y = y;
Timer t = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (r<200) {
r++;
} else {
r=10;
}
revalidate();
repaint();
}
});
t.start();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.CYAN);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawOval(x-r,y-r,2*r,2*r);
}
public static void Gui() {
JFrame f = new JFrame("Water Ripples");
JPanel p0 = new JPanel();
p0.setBackground(Color.WHITE);
f.add(p0);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setBounds(100,100,600,500);
f.setVisible(true);
f.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Ripples rG = new Ripples(e.getX(), e.getY());
rG.setBackground(Color.WHITE);
f.add(rG);
}
});
}
public static void main(String[] args) {
Gui();
}
}
那么我该如何解决这个问题,以便让圈子彼此独立成长呢?我更喜欢上面代码的解决方案/改进/提示,因为我认为它的结构比第二个更好。此外,对于没有将代码拆分为更多类以及可能不遵守命名约定,我深表歉意。感谢您的帮助,非常感谢!
解决方案
我更喜欢上面代码的解决方案/改进/提示
第二个代码更好,因为它使用:
- 一个自定义类,包含有关要绘制的对象的信息
- 一个 ArrayList 包含要绘制的对象
- 动画的计时器。
因为我认为它的结构比第二个更好。
不是很好的理由。使用提供所需功能的代码。
自己重构代码。这是学习经历的一部分。
第二个代码的问题:
- 它不编译。为什么要发布无法编译的代码?这意味着你甚至没有测试过它。
- 创建对象时分配初始半径
Position
。 - 当 Timer 触发时,您需要遍历 ArrayList 以更新每个
Position
对象的半径。 Position
绘制代码中使用了对象的半径。
作为一个额外的变化,也许调用Position
class Ripple
。Color
然后,您可以为波纹添加另一个自定义属性。然后,当您将 ArrayList 添加Ripple
到 ArrayList 时,您会随机生成一个 Color。然后在绘画方法中使用Ripple
类的 Color 属性。这就是您如何使对象和绘画更加灵活和动态的方式。
推荐阅读
- react-native - Invariant Violation error when using Redux with react-native
- r - How can I inject symbols for autocompletion into R in a specific context?
- java - 更改矢量应用程序图标的背景颜色
- jquery - want to run jquery one time on multiple reload
- android - IsConnected 是否包含流量节省程序状态?
- mapbox - Mapbox GL JS:JSON点消失
- material-ui - 不确定为什么 MultiSelect 样式不符合预期 - Material UI
- bash - 将引号添加到 appveyor.yml 回显行
- javascript - Sinon Spy + ReactJs 属性初始化器语法
- android - 如何使活动适合屏幕?