如何让 class 创建自己的 Graphics 实例

How to have a class create its own instance of Graphics

我有一个名为 CharMove 的 class,其中包含 paint(Graphics g) 方法和一些自定义方法。 class 应该创建一个正方形,然后在屏幕上随机移动该正方形。但是,当我在我的世界 Class 中创建此 class 的两个实例时,只出现一个方块。首先方块不动但显示新坐标,然后在运行 5 次后方块开始随机移动。我认为程序在 Graphics 方法上遇到了问题,因为只创建了一个正方形,当 CharMove class 应该创建 Graphics.I 的另一个实例时已在线搜索但找不到创建方法提前 Graphics.Thanks 的不同实例。

CharMove Class

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

public class CharMove extends JPanel {
    int x = 250;
    int y = 250;  
    public void paint(Graphics g) { 
        Graphics pane = (Graphics2D) g;
        pane.setColor(Color.blue);
        pane.fillRect(x, y, 10, 10);  

    }

    public void movement(JFrame frame) { 
        for (int i=0;i<5;i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
                this.x = Getx(this.x,frame); 
                this.y = Gety(this.y,frame);
                frame.repaint();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public int Getx(int a, JFrame frame) { 
        Random rn = new Random();
        int xnum = rn.nextInt(10)-5; 
        a += xnum; 
        System.out.println("x:" + a); 
        return a;
    } 
    public int Gety(int b, JFrame frame){ 
        Random rn = new Random();
        int ynum = rn.nextInt(10)-5; 
        b += ynum; 
        System.out.println("y:" + b); 
        return b;
    } 
}

世界Class

import java.awt.*;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import java.util.Random;
public class World {


    public static void main(String[] args) {  

        JFrame game = new JFrame();
        game.setTitle("Matrix");
        game.setSize(500, 500);;
        game.getContentPane().setBackground(Color.white);
        game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        game.setVisible(true);  
        CharMove char1 = new CharMove(); 
        CharMove char2 = new CharMove();
        game.add(char1);  
        game.add(char2);
        char1.movement(game);  
        char2.movement(game);
    } 
}

在 swing 中,你所有的绘画都应该在 paintComponent(Graphics g) 中(重命名你的方法)

要制作动画,您应该使用 Swing Timer(带有 ActionListener)来更新动画项目的位置。完成后,计时器应调用 repaint();

public void actionPerformed(ActionEvent ae) {
    this.x = Getx(this.x,frame); 
    this.y = Gety(this.y,frame);
    frame.repaint();

}

However,when I create two instances of this class in my World Class,only one square appears.

JFrame 的默认布局管理器是 BorderLayout。

    game.add(char1);  
    game.add(char2);

当您在没有指定约束的情况下添加组件时,这两个组件都会添加到 CENTER。但是,CENTER 只能添加一个组件,因此只会显示最后添加的一个。

尝试:

    game.add(char1, BorderLayout.PAGE_START);  
    game.add(char2, BorderLayout.PAGE_END);

但是,当您执行此操作时,组件将不会显示,因为它们具有 (0, 0) preferredSize。因此,您还需要重写 CharMove class.

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

另外,自定义绘画应该在paintComponent(...)方法中完成,需要在开始时调用super.paintComponent(...)来清除背景。

您的 movement() 方法中的 repaint() 方法应该在面板上,而不是框架上,因为您正在更改面板的属性。

每个 CharMove 本质上是一个 JPanel,它在绘制时在其自身某处绘制一个大小为 10 的正方形。您正在向 game JFrame 添加两个 CharMove 面板(实际上是将它们添加到默认内容窗格,该窗格具有子类 BorderLayout)。由于您没有提供布局约束对象,实际上两个面板都被添加到内容窗格的 BorderLayout.CENTER,第二个完全覆盖了第一个。

要更正此问题,您应该修改 CharMove 以便它绘制所有方块(例如,通过维护一个数组或某种正方形集合,并在 paint 方法中绘制所有方块)并仅添加一个面板到 JFrame。

除了这个问题,当您在 movement 方法中为方块设置动画时,您会阻塞事件调度线程,这意味着在动画期间您将无法移动任何其他 windows 或响应任何鼠标点击或其他输入。接受 ControlAltDel 关于使用 Swing Timer 动画的建议来纠正这个问题。