图形列表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);
    }
}