Java 如何从其他类绘制到JPanel(类扩展)

Java 如何从其他类绘制到JPanel(类扩展),java,swing,jpanel,java-2d,Java,Swing,Jpanel,Java 2d,我的确有一个错误 public class Main extends JPanel implements Runnable { private static final int WIDTH = 1000; private static final int HEIGHT = 800; TerranGenartor gen = new TerranGenartor(); public Main() { setSize(WIDTH, HEIGHT);

我的确有一个错误

public class Main extends JPanel implements Runnable {

    private static final int WIDTH = 1000;
    private static final int HEIGHT = 800;
    TerranGenartor gen = new TerranGenartor();

    public Main() {
        setSize(WIDTH, HEIGHT);
        gen.run();
    }

    public void paintComponents(Graphics g) {
        repaint();

    }

    public void run() {
    }
}
我的
terrangenerator
职业

 TerranGenartor gen = new TerranGenartor(); 
public class TerranGenartor implements Runnable {

    Main main = new Main();
    Graphics g;
    Random r = new Random();
    int SMIN = 1;
    int SMAX = 3;
    int i = 0;
    int num;
    int x = 0;
    int y = 0;
    public Color grass = new Color(124, 252, 0);
    public Color stone = new Color(190, 190, 190);
    public Color dirt = new Color(139, 69, 19);
    boolean Runn = false;

    public void start() {
        Runn = true;
        System.out.println("Working...");
    }

    public TerranGenartor() {
        Runn = true;
    }

    protected void paintComponent(Graphics g) {
        g = main.getGraphics();
        while (Runn) {
            if (i <= 1000) {
                num = r.nextInt(SMAX - SMIN + 1) + SMIN;
                switch (num) {
                    case 1:
                        g.setColor(grass);
                        break;
                    case 2:
                        g.setColor(stone);
                        break;
                    case 3:
                        g.setColor(dirt);
                        break;
                    default:
                        g.setColor(grass);
                        break;
                }
                g.fillRect(x, y, 50, 50);
                x += 50;
                System.out.println(i);
                System.out.println("X: " + x);
                try {
                    Thread.sleep(15);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void run() {
        while (Runn) {
            paintComponent(g);
        }
    }
}
这门课只是遵守并运行它,我认为一切都很好

问题是,当我想从
TerranGenerator
类中绘制时,它不起作用。
JPanel上没有显示任何内容

让我们从

setSize(宽度、高度)来自
Main
。这是个坏主意。布局管理器可以覆盖这些值(假设您正在使用布局管理器)。您应该重写
getPreferredSize
并将它们返回到那里

public class The_Runner {

    Main main = new Main();
    JFrame frame = new JFrame();
    private static final int WIDTH = 1000;
    private static final int HEIGHT = 800;
    String TITLE = "Map gen.";

    public The_Runner() {
        frame.setSize(WIDTH, HEIGHT);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setTitle(TITLE);
        frame.add(main);
    }

    public static void main(String[] args) {
        The_Runner runner = new The_Runner();
    }
}    
然后这个(也来自
Main

决不能从
paint
方法中调用
repaint
,也不能调用任何可能导致调用
repaint
的方法,否则将陷入一个无限循环的厄运,将使CPU循环高达100%

Main
terrangenerator
之间有一个循环引用。基本上,您已经在每个类中声明了每个类的引用,编译器无法处理这个问题,因为它无法在不先构建另一个类的情况下构建一个类

永远不要这样做

public void paintComponents(Graphics g) {
    repaint();
}
getGraphics
is可以返回
null
值。此方法返回的结果值只不过是应用程序使用的当前图形上下文的快照。这可以在下一个绘制周期中取消引用或更改

永远不要从事件调度线程(EDT)外部绘制/更新/修改/创建任何Swing组件,如果这样做的话,您可能最终会得到奇怪的绘制工件,因为您尝试更新图形,EDT也会更新它,这永远都不漂亮

你可能想看看

已更新

我怀疑您的“主要”问题(除了代码无法编译之外)将是
repaint
请求正在清除您使用
main.getGraphics

您还应该在
Main#paintComponent
方法中调用
super.paintComponent

用示例更新


1)要更快地获得更好的帮助,请发布一个。2) 使用
BufferedImage
作为画布通常更容易进行自定义渲染。该源中过多的空白“空白”行是怎么回事?只需要一行空白,源代码中的大多数代码都不能提高可读性,而且没有一行可以加快代码的运行速度。很抱歉,这是我第一个被问到的问题,对这个网站来说很新。重要的不是第一次就把它做好,而是从经验中学习。欢迎来到SO.:)
public void paintComponents(Graphics g) {
    repaint();
}
g = main.getGraphics();