【问题标题】:Java: repaint() method, why is it being temperamental?Java:repaint() 方法,为什么它是喜怒无常的?
【发布时间】:2014-02-04 17:15:41
【问题描述】:

我有一段代码用于我正在开发的一个非常基本的 2d 平台游戏,但我无法开始工作。游戏本身运行良好,但由于某种原因标题屏幕不会出现。我设法将其归结为从 title() 方法调用时 repaint() 方法没有做任何事情的事实。无论我如何尝试调用它,导致事件/设置另一个计时器,paintComponent 方法都没有做任何事情,甚至没有出现窗口。尽管如此,与我非常相似的 level() 方法确实会导致窗口出现并执行 paintComponent 方法。

我很抱歉代码有多丑陋,这对我来说是一个实验,所以目前有点不整洁。任何有关如何解决此问题的帮助将不胜感激。

这是 JPanel 类的代码,我遇到了问题。

public class Screen extends JPanel implements ActionListener{

int currentScreen;
Image title;
Image background;
Image ship;
Image black;
private Timer timer;
private Level lvl;

public Screen(){

    addKeyListener(new TAdapter());
    setFocusable(true);
    setBackground(Color.BLACK);
    setDoubleBuffered(true);

    title();
    level();
}


public void paintComponent(Graphics g) {

    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    if(currentScreen == 0) {
        g2d.drawImage(title, 0, 0, this);
    }
    else if(currentScreen == 1){
        g2d.drawImage(background, 0, 0, this);
        g2d.drawImage(lvl.getAvImage(), lvl.getAvX(), lvl.getAvY(), this);
        g2d.setFont(new java.awt.Font("SansSerif", Font.PLAIN, 12));
        for(int i=0;i<4;i++)
            for(int j=0; j<4; j++){
                g2d.drawImage(lvl.getPlijImage(i,j), lvl.getPlijX(i,j), lvl.getPlijY(i,j), this);
                g2d.drawString(Integer.toString(lvl.getPlijCurrent(i,j)), lvl.getPlijX(i,j)+64, lvl.getPlijY(i,j)+16);

            }
        g2d.drawImage(spaceship, 0, 0, this);
        g2d.drawImage(black, 0, 736, this);
        g2d.setColor(Color.WHITE);
        g2d.drawString(lvl.getSqDisplay(), 450, 32);
    }
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

public void title(){

    ImageIcon ii = new ImageIcon(this.getClass().getResource("Title.png"));
    title = ii.getImage();
    currentScreen = 0;
    repaint(); //doesn't invoke paint
    Scanner reader = new Scanner(System.in); //not relevant, just getting it to stop before opening level
    int a=reader.nextInt();
}

public void level(){

    lvl = new Level(1);
    ImageIcon ii = new ImageIcon(this.getClass().getResource("Background.png"));
    background = ii.getImage();
    ii = new ImageIcon(this.getClass().getResource("Ship.png"));
    ship = ii.getImage();
    ii = new ImageIcon(this.getClass().getResource("Black.png"));
    black = ii.getImage();
    currentScreen = 1;
    timer = new Timer(10, this);
    timer.start();

}

public void actionPerformed(ActionEvent e) {
    lvl.actionPerformer(e);
    repaint(); //does invoke paintComponent, but not when I jump here from the title bit
}

private class TAdapter extends KeyAdapter {

    public void keyReleased(KeyEvent e) {
        if(currentScreen == 1) lvl.keyReleased(e);
    }

    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if(currentScreen == 1) lvl.keyPressed(e);
        else if((currentScreen == 0)&&(key == KeyEvent.VK_ENTER)){
            onTitle = false;
        }
    }
}

}

【问题讨论】:

    标签: java image swing paint event-dispatch-thread


    【解决方案1】:
    Scanner reader = new Scanner(System.in); //not relevant, just getting it to stop before opening level
    int a=reader.nextInt();
    

    我不敢苟同。这(很可能)是您遇到问题的原因。

    这两行简单的代码阻止了事件调度线程处理任何新事件,包括重绘请求。这意味着,在title 方法返回之前,不会发生新的绘制

    查看Concurrency in Swing了解更多详情。

    有许多可能的解决方案,但您需要提供更多详细信息,说明您正在尝试实现的目标,然后它们才会有意义...

    【讨论】:

    • 啊好吧,基本上标题屏幕上写着“Press enter to continue”。我打算使用 TAdapter 来实现这一点,但我试图让屏幕首先工作。我尝试了其他几种方法让它在关卡执行之前停止(无限循环、等待等),但它们没有任何作用,或者只是导致了其他问题。
    • 感谢您的提示,我已经设法解决了我的问题!我混淆了一些方法,所以 repaint() 只以一种方式被调用,我所有的肤浅的东西都是单独处理的。非常感谢您的帮助!
    • 更好的解决方案可能是使用多个面板和卡片布局。从带有按钮的面板开始,当激活该按钮时,会将视图更改为“游戏”面板。您甚至可以使用键绑定,但按钮可以让您同时使用鼠标和键盘
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 2016-05-01
    • 2014-09-30
    • 2012-03-25
    相关资源
    最近更新 更多