【问题标题】:How do I correctly set up canvas capable on running a simulation如何正确设置能够运行模拟的画布
【发布时间】:2015-11-19 12:52:52
【问题描述】:

我是 Java 新手,最近才了解面向对象编程。我正在尝试创建一个可以运行模拟的程序,一般的想法是我想要屏幕的一部分专用于按钮/滑块,而另一部分专用于运行模拟的画布。现在我并不担心模拟本身,我只是想在画布上获得一些图形(比 JFrame 小)。

这是我的代码(我会尝试在下面留下一些解释)

public class Launcher {

    public static void main(String[] args){

        Display display = new Display();

    }

}

.

import java.awt.*;
import javax.swing.*;

public class Display {

    public final int width = 1280, height = 720;
    public final int cwidth = 894, cheight = 504;
    public final String title = "Mechancis Simulator";
    private JFrame frame;
    //private JPanel panel;
    private Canvas canvas;
    private Simulation simulation;

    public Display(){

        initDisplay();

        simulation = new Simulation();

    }

    private void initDisplay(){

        frame = new JFrame(title);
        frame.setSize(width, height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        /*panel = new JPanel();
        panel.setSize(width, height);
        panel.setLocation(0,0); */

        canvas = new Canvas();
        canvas.setPreferredSize(new Dimension(cwidth, cheight));
        canvas.setMaximumSize(new Dimension(cwidth, cheight));
        canvas.setMinimumSize(new Dimension(cwidth, cheight));
        canvas.setLocation(width - (cwidth +15), 15);

        //panel.add(canvas);
        frame.add(canvas);

        /* Add code for buttons/sliders/boxes here */

        /* Add these to panel */

    }

    public JFrame getFrame(){
        return frame;
    }

    public Canvas getCanvas(){
        return canvas;
    }

}

.

import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.*;
import javax.swing.*;

public class Simulation extends Display implements Runnable {

    private boolean running = false;
    private Thread thread;

    private BufferStrategy bs;
    private Graphics g;

    public Simulation(){

    }

    private void init(){

    }

    private void tick(){

    }

    private void render(){
        bs = getCanvas().getBufferStrategy();
        if(bs == null){
            getCanvas().createBufferStrategy(3);
            return;
        }
        g = bs.getDrawGraphics();
        //Draw Here!


        //End Drawing!
        bs.show();
        g.dispose();
    }

    public void run(){

        init();

        while(running){
            tick();
            render();
        }

        stop();

    }

    public synchronized void start(){
        if(running)
            return;
        running = true;
        thread = new Thread(this);
        thread.start();
    }

    public synchronized void stop(){
        if(!running)
            return;
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

当我运行程序时,窗口开始变得疯狂。我对类和线程很陌生,所以也许这就是问题所在。我只想在 Display 对象中设置 Frame 和 Canvas 后能够运行模拟。

谢谢。

【问题讨论】:

  • 您认为class Simulation extends Display 会为您提供什么帮助?
  • Swing 大多不是线程安全的:大多数 Swing 方法只能从应用程序的事件调度线程 (EDT) 安全地调用。也就是说,它们只能从事件处理程序中安全地调用。如果您想在屏幕上设置动画,可以使用Timer 来安排 EDT 将在未来执行一次或在未来定期执行的任务。
  • 如果您的Simulation 进行大量计算并且需要在后台线程中运行,那么它可以调用SwingUtilities.invokeLater(t) 要求EDT 执行一些任务t 来完成绘画.
  • @BeyelerStudios 对不起,我对对象和类很陌生。我知道我可以在 Simulation 类中声明一个新的 Display 对象,但是我认为如果我这样做,它将引用一个不同的 Display 对象(不是来自启动器的那个),我的印象是这会导致创建一个额外的 JFrame 或其他东西。如果我可以将模拟作为 Display 的扩展,那么我就不需要声明一个新的显示对象来访问 getCanvas()。我知道这里很可能是错的,但我不确定为什么。

标签: java multithreading class oop


【解决方案1】:

你所做的基本上是这样的:

class Display {
    private final Simulation sim;
    public Display() { sim = new Simulation(); }
}

class Simulation extends Display {
    public Simulation() { }
}

当您创建一个新的Display 时,构造函数会创建一个新的Simulation,它是一个Display,它创建一个新的Simulation,它是一个Display,它创建一个新的Simulation,它是一个@987654329 @ 创建一个新的Simulation...*

所以不要。您的Simulation 没有理由成为展示品并拥有另一个Simulation。如果您希望Display 中的所有控件定义一个构造函数,该构造函数将其显示的Simulation 作为参数,并在您创建它时对其进行模拟:

class Display {
    private final Simulation sim;
    public Display(Simulation sim) { this.sim = sim; }
}

class Simulation {
}

...

Display display = new Display(new Simulation());

*如果您想了解更多信息,我建议您在 Google 上搜索有关继承的教程。下面是 tutorial from oracle 来帮助您入门:“您可以编写一个子类构造函数来调用超类的构造函数,隐式 或使用关键字 super。”您的代码示例构造函数super() 被隐式调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-01
    • 2015-03-08
    • 2014-11-20
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-12-22
    相关资源
    最近更新 更多