Java:repaint()方法,为什么它是喜怒无常的?

Java:repaint()方法,为什么它是喜怒无常的?,java,image,swing,paint,event-dispatch-thread,Java,Image,Swing,Paint,Event Dispatch Thread,我有一段代码,用于我正在开发的一个相当基本的2d平台游戏,但我无法开始工作。游戏本身运行良好,但由于某些原因,标题屏幕不会出现。我设法将这归因于这样一个事实,即当从title()方法调用repaint()方法时,它没有做任何事情。无论我如何尝试调用它,导致一个事件/设置另一个计时器,paintComponent方法都没有做任何事情,甚至窗口也没有出现。尽管如此,level()方法(看起来与我非常相似)确实会导致窗口出现并执行paintComponent方法 我很抱歉代码有多难看,这对我来说是一个

我有一段代码,用于我正在开发的一个相当基本的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;
        }
    }
}
公共类屏幕扩展JPanel实现ActionListener{
电流屏;
图像标题;
图像背景;
形象船;
图像黑色;
私人定时器;
私有级lvl;
公共屏幕(){
addKeyListener(新的TAdapter());
设置聚焦(真);
挫折背景(颜色:黑色);
setDoubleBuffered(真);
title();
水平();
}
公共组件(图形g){
超级组件(g);
Graphics2D g2d=(Graphics2D)g;
如果(当前屏幕==0){
g2d.drawImage(标题,0,0,this);
}
否则如果(当前屏幕==1){
g2d.drawImage(背景,0,0,this);
g2d.drawImage(lvl.getAvImage(),lvl.getAvX(),lvl.getAvY(),this);
setFont(新的java.awt.Font(“SansSerif”,Font.PLAIN,12));
对于(int i=0;i
我不敢苟同。这(很可能)就是你遇到问题的原因

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

请查看以了解更多详细信息


有很多种可能的解决方案,但您需要提供更多关于您试图实现的目标的详细信息,然后这些解决方案才有意义……

Ah好的,基本上标题屏幕显示“按enter键继续”我本来打算用TAdapter来实现这一点,但我试图先让屏幕工作。我尝试了几种其他方法让它在执行级别之前停止(无限循环、等待等)但是它们并没有起到什么作用,或者只是引起了其他问题。多亏了你的提示,我成功地解决了我的问题!我把一些方法弄得乱七八糟,所以重新绘制()只是用一种方式调用,我所有肤浅的东西都是分开处理的。非常感谢您的帮助!更好的解决方案可能是使用多个面板和一个卡片布局。从一个带有按钮的面板开始,当激活按钮时,将视图更改为“游戏”你甚至可以使用键绑定,但一个按钮可以让你同时使用鼠标和键盘
Scanner reader = new Scanner(System.in); //not relevant, just getting it to stop before opening level
int a=reader.nextInt();