【问题标题】:how to move multiple objects in JPanel如何在 JPanel 中移动多个对象
【发布时间】:2016-01-21 04:11:16
【问题描述】:

我想创建多个同时独立移动的正方形,我认为最有效的方法是通过 Graphics2D 中的变换方法,但我不知道如何使它适用于每个正方形。我想要方形对象是自包含的并创建自己的变换(实例变换)。这是我到目前为止所拥有的。

转换面板

import javax.swing.*; 
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class TranformPanel extends JPanel {
    private int[] xcoords = {250,248,253,255,249}; 
    private int[] ycoords = {250,253,249,245,250}; 
    private double randomx = 0; 
    private double randomy = 0;
    public void paintComponent(Graphics g) 
    { 
        super.paintComponent(g); 
        drawTransform(g,randomx,randomy);
    } 
    private void drawTransform(Graphics g,double randomx,double randomy) 
    {  
        Random rn = new Random(); 
        int xnum = rn.nextInt(10)-5; 
        randomx = xnum; 
        int ynum = rn.nextInt(10)-5; 
        randomy = ynum;

        Rectangle rect = new Rectangle(250,250,10,10);  
        AffineTransform transform = new AffineTransform();   
        Graphics2D g2d = (Graphics2D)g;   

        transform.translate(randomx,randomy);
        g2d.draw(transform.createTransformedShape(rect));  

        }
    }

变换绘图

import java.awt.*; 
import javax.swing.*; 
import java.awt.geom.AffineTransform;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class TransformDraw{ 
    private static TranformPanel panel = new TranformPanel();
    public static void main(String[] args) {    
        // Setup our JFrame details 
        JFrame frame = new JFrame();
        frame.setTitle("Transform Polygon Example");
        frame.setSize(500,500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());   
        frame.setVisible(true);
        frame.add(panel); 
        Scanner input = new Scanner(System.in); 
        for (int i=0;i<10;i++) 
        { 
        try {
            TimeUnit.SECONDS.sleep(1);
            frame.repaint(); 
        } catch (InterruptedException e) {
            e.printStackTrace();
            }
        } 
    } 
}

感谢是提前!

【问题讨论】:

  • 创建一个知道单个盒子在哪里的类,当你需要时用它来绘制盒子
  • MadProgrammer- 请详细说明。我将如何跟踪一个盒子的位置,我是否需要为每个盒子创建一个该类的对象?另外,我将如何转换它的位置?

标签: java graphics jpanel transform graphics2d


【解决方案1】:

首先创建可以管理其位置(和其他属性)并且可以“绘制”的东西

public interface Box {
    public void update(Dimension size);
    public void paint(Graphics2D g2d);
}

所以,这是非常基本的,它所能做的就是更新(在给定区域内)并被绘制。您可以根据您的特定需求公开其他属性(例如边界框)

接下来,我们需要一个简单的实现,比如...

public class DefaultBox implements Box {

    private Color color;
    private Rectangle bounds;

    private int xDelta;
    private int yDelta;

    public DefaultBox(Color color, Dimension size) {
        this.color = color;
        bounds = new Rectangle(new Point(0, 0), size);

        xDelta = 1 + (int) (Math.random() * 10);
        yDelta = 1 + (int) (Math.random() * 10);
    }

    @Override
    public void update(Dimension size) {
        bounds.x += xDelta;
        bounds.y += yDelta;

        if (bounds.x < 0) {
            bounds.x = 0;
            xDelta *= -1;
        } else if (bounds.x + bounds.width > size.width) {
            bounds.x = size.width - bounds.width;
            xDelta *= -1;
        }
        if (bounds.y < 0) {
            bounds.y = 0;
            yDelta *= -1;
        } else if (bounds.y + bounds.height > size.height) {
            bounds.y = size.height - bounds.height;
            yDelta *= -1;
        }
    }

    @Override
    public void paint(Graphics2D g2d) {
        g2d.setColor(color);
        g2d.fill(bounds);
    }

}

现在,它维护了一个简单的Rectangle 实例,它描述了对象的位置和大小,它还维护了关于颜色和速度的属性。

update 被调用时,它会更新它的位置并进行一些简单的边界检查以确保框保持在指定区域内。

paint 被调用时,它只是简单地绘制自己。

最后,我们需要一些方法来更新和绘制这些框......

public class TestPane extends JPanel {

    private List<Box> boxes;
    private Color[] colors = {Color.RED, Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.WHITE, Color.YELLOW};

    public TestPane() {
        boxes = new ArrayList<>(25);
        for (int index = 0; index < 100; index++) {
            Color color = colors[(int) (Math.random() * colors.length)];
            int width = 10 + (int) (Math.random() * 9);
            int height = 10 + (int) (Math.random() * 9);
            boxes.add(new DefaultBox(color, new Dimension(width, height)));
        }

        Timer timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                for (Box box : boxes) {
                    box.update(getSize());
                }
                repaint();
            }
        });
        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Box box : boxes) {
            Graphics2D g2d = (Graphics2D) g.create();
            box.paint(g2d);
            g2d.dispose();
        }
    }

}

好的,再说一遍,这很简单。它维护BoxListTimer 的Swing 以定期更新BoxList,调用他们的update 方法。 Timer 简单地调用repaint,最终调用paintComponent,然后在Box 的每个实例上调用paint

100 盒...

【讨论】:

  • 感谢您的详细说明。我复制并粘贴了代码,但它不适合 Ecplise 的启动参数。任何解决方案?
  • 我不知道 "but it doesn't fit the launch parameters of Ecplise" 是什么意思,我不使用 Eclipse。代码可以从命令行编译和运行就好了,代码有特别之处
  • 别担心。我只是愚蠢,忘记在不同的 java 文件中实际创建 TestPanel 对象>.
  • 欢迎来到我的世界:P
猜你喜欢
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多