图形列表2D
List of graphics2D
为什么下面这段代码不起作用?我想每 200 毫秒向 ArrayList 添加新的 Ovals 并显示它们并 运行 它们一一显示。当我 运行ning 一个粒子 s.runner(); 时它工作正常;但它似乎并不 运行 我所有的粒子。
主线:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.Timer;
public class ExempelGraphics extends JFrame implements ActionListener {
Timer t;
private int inc = 0;
ArrayList<Surface> particle = new ArrayList<>();
Surface s;
public ExempelGraphics() {
t = new Timer(10, this);
t.start();
s = new Surface(10, 10);
initUI();
}
private void initUI() {
add(s);
setSize(350, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
// s.runner();
// add
if (inc++ % 20 == 0) {
particle.add(new Surface(10, 10));
}
// display
for (int i = 0; i < particle.size(); i++) {
Surface p = particle.get(i);
p.runner();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ExempelGraphics ex = new ExempelGraphics();
ex.setVisible(true);
}
});
}
}
图形:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Surface extends JPanel {
private int locX = 0;
private int locY = 0;
public Surface(int locX, int locY) {
this.locX = locX;
this.locY = locY;
}
public void runner() {
locX = locX + 1;
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval(locX, locY, 10, 10);
}
}
我认为您的程序结构已损坏。你应该只有一个 JPanel 在这里做绘图,它的 paintComponent 被覆盖,你的 Surface class 应该是 logical class 而不是组件 class——换句话说,不要让它扩展 JPanel,而是在绘制椭圆的地方给它一个 public void draw(Graphics g)
方法。然后让绘图 JPanel 保存这些表面的 ArrayList,并在主要的 JPanel 的 paintComponent 方法中,遍历表面,调用每个表面的绘制方法。
另外你的Timer的延迟是不现实的而且太小了。 15 会更现实。
此外,不要从表面内部调用 repaint()
,因为那样会产生过多不必要的重绘调用。在所有 Surface 对象上调用 runner 方法后,而是从 Timer 的 ActionListener 中调用它。
另请注意,每次以默认方式将组件添加到 JFrame 的 contentPane 时,都会掩盖之前添加的组件。如果您遵循我上面的建议,这不是问题,因为您只需向其中添加一个 JPanel。
例如:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class ExampleGraphics2 extends JPanel {
private static final int PREF_W = 650;
private static final int PREF_H = 500;
private static final int TIMER_DELAY = 20;
private List<Surface> surfaces = new ArrayList<>();
public ExampleGraphics2() {
new Timer(TIMER_DELAY, new TimerListener()).start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Surface surface : surfaces) {
surface.draw(g);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
private int index = 0;
@Override
public void actionPerformed(ActionEvent e) {
index++;
index %= 20;
if (index == 0) {
surfaces.add(new Surface(10, 10));
}
for (Surface surface : surfaces) {
surface.runner();
}
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Example Graphics 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ExampleGraphics2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
package foo1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class Surface {
private int locX = 0;
private int locY = 0;
public Surface(int locX, int locY) {
this.locX = locX;
this.locY = locY;
}
public void runner() {
locX = locX + 1;
}
public void draw(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval(locX, locY, 10, 10);
}
}
为什么下面这段代码不起作用?我想每 200 毫秒向 ArrayList 添加新的 Ovals 并显示它们并 运行 它们一一显示。当我 运行ning 一个粒子 s.runner(); 时它工作正常;但它似乎并不 运行 我所有的粒子。
主线:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.Timer;
public class ExempelGraphics extends JFrame implements ActionListener {
Timer t;
private int inc = 0;
ArrayList<Surface> particle = new ArrayList<>();
Surface s;
public ExempelGraphics() {
t = new Timer(10, this);
t.start();
s = new Surface(10, 10);
initUI();
}
private void initUI() {
add(s);
setSize(350, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
// s.runner();
// add
if (inc++ % 20 == 0) {
particle.add(new Surface(10, 10));
}
// display
for (int i = 0; i < particle.size(); i++) {
Surface p = particle.get(i);
p.runner();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ExempelGraphics ex = new ExempelGraphics();
ex.setVisible(true);
}
});
}
}
图形:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Surface extends JPanel {
private int locX = 0;
private int locY = 0;
public Surface(int locX, int locY) {
this.locX = locX;
this.locY = locY;
}
public void runner() {
locX = locX + 1;
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval(locX, locY, 10, 10);
}
}
我认为您的程序结构已损坏。你应该只有一个 JPanel 在这里做绘图,它的 paintComponent 被覆盖,你的 Surface class 应该是 logical class 而不是组件 class——换句话说,不要让它扩展 JPanel,而是在绘制椭圆的地方给它一个 public void draw(Graphics g)
方法。然后让绘图 JPanel 保存这些表面的 ArrayList,并在主要的 JPanel 的 paintComponent 方法中,遍历表面,调用每个表面的绘制方法。
另外你的Timer的延迟是不现实的而且太小了。 15 会更现实。
此外,不要从表面内部调用 repaint()
,因为那样会产生过多不必要的重绘调用。在所有 Surface 对象上调用 runner 方法后,而是从 Timer 的 ActionListener 中调用它。
另请注意,每次以默认方式将组件添加到 JFrame 的 contentPane 时,都会掩盖之前添加的组件。如果您遵循我上面的建议,这不是问题,因为您只需向其中添加一个 JPanel。
例如:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class ExampleGraphics2 extends JPanel {
private static final int PREF_W = 650;
private static final int PREF_H = 500;
private static final int TIMER_DELAY = 20;
private List<Surface> surfaces = new ArrayList<>();
public ExampleGraphics2() {
new Timer(TIMER_DELAY, new TimerListener()).start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Surface surface : surfaces) {
surface.draw(g);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
private int index = 0;
@Override
public void actionPerformed(ActionEvent e) {
index++;
index %= 20;
if (index == 0) {
surfaces.add(new Surface(10, 10));
}
for (Surface surface : surfaces) {
surface.runner();
}
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Example Graphics 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ExampleGraphics2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
package foo1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class Surface {
private int locX = 0;
private int locY = 0;
public Surface(int locX, int locY) {
this.locX = locX;
this.locY = locY;
}
public void runner() {
locX = locX + 1;
}
public void draw(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval(locX, locY, 10, 10);
}
}