有没有办法从ouside它的类上绘制JPanel对象?

时间:2015-11-08 05:55:53

标签: java swing jpanel

我搜索并发现了几个类似的问题,但没有任何适用于我的情况,所以我去了。

我试图制作一个不同级别的游戏,每个级别的游戏都完全不同。

最初,我的代码看起来像这样并且运行良好:

public class Life extends JPanel{

private Story story;

public Life(){
    story = new Story(this);

}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    story.render(g)

public void terminate(){
    story.terminate();
    System.out.println("Terminated");
}

public static void main(String[] args){
    final JFrame frame = new JFrame("Life");
    final Life life = new Life();
    frame.add(life);
}
}



public class Story {

private int phase;
private Life life;


public Story(Life life){
    this.life = life;
    phase = 0;
}

public void render(Graphics g){
    if(phase == 0) levelOneRender(g);
    if(phase == 1) levelTwoRender(g);
}
}

我很担心每次游戏时都会浪费时间来检查我所处的阶段。由于我计划有20多个阶段,因此代码会快速效率低下。

所以我有一个想法,就是简单地将JP对象中的Graphics对象从我的Life对象传递到我的Story对象,并将Jpanel绘制在每个阶段的不同类中,如下所示:

public class Life extends JPanel{

public Life(){

    story = new Story(this);
}


public static void main(String[] args){
    final JFrame frame = new JFrame("Life");
    final Life life = new Life();

}

}


public class Story {

private int phase;
private Intro intro;
private Life life;


public Story(Life life){
    this.life = life;
    phase = 0;
    intro = new Intro(this);
}

public void nextPhase(){
    this.phase++;
}


public Life getLife() {
    return this.life;
}
}

public class Intro {

private static final int DELAY = 100; // in milliseconds, so 10 ticks per second

private Timer timer;
private Story story;
private Graphics g;
private int counter;


public Intro(Story story) {
    this.story = story;
    this.g = story.getLife().getGraphics();
    this.counter = 0;

    timer = new Timer(DELAY, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            tick();
            story.repaint();
        }
    });
    timer.start();
}

public void tick(){
    if(counter <= 40){
        terminate();
    }
    counter++;
    render();
}

public void render(){
    story.getLife().paint(g);
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g2.draw(new Rectangle(0,0,10,10));


}

public void terminate(){
    timer.stop();
    story.nextPhase();
}
}

不幸的是,这不起作用,如story.getLife()。paint(g);在类Intro中,当我运行它时抛出nullPointerException。而且我很确定这不是我尝试此问题的唯一问题。

有没有正确的方法去做我想要的事情?

非常感谢你的时间。任何见解都将不胜感激。

1 个答案:

答案 0 :(得分:1)

public void render(Graphics g){
    if(phase == 0) levelOneRender(g);
    if(phase == 1) levelTwoRender(g);
}

这并不像你想象的那么大。你现在拥有的很好。但是可以避免这些检查(正如您所要求的那样)。

不是在单独的方法中处理每个级别的绘画,而是在单独的对象中处理它们:

public bstract class Level {
    public abstract void paint(Graphics g);
}

public final class LevelOne extends Level {
    public void paint(Graphics g) {
        //...
    }
}

public final class LevelTwo extends Level {
    public void paint(Graphics g) {
        //...
    }
}

这样,您无需检查int值以查看要绘制的渲染,而只需切换Level值即可呈现新级别:

Level one = new LevelOne();
Level two = new LevelTwo();

Level currentLevel = one;

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    currentLevel.paint(g);
}

只需切换level的值即可呈现不同级别