繁体   English   中英

将 JLayerPane 添加到 JFrame 时出现延迟

[英]Delay when adding JLayerPane to JFrame

我需要使用 Swing 在 Java 中制作一个刽子手游戏。 我在 Photoshop 中制作了我的刽子手人物,并使用完整图像作为背景层,然后使用 JlayeredPane 将其他组件放在顶部。 但是,当我添加 JFrame 并打开 window 时,总是会有一点延迟。 我尝试创建一个按钮以在单击时在 JLayeredPane 上添加和删除,但这会导致更大的延迟。 任何帮助将不胜感激。

public class Game_Screen extends JLayeredPane {
    
    private JLabel hangman;
    
    public Game_Screen() {
        super();
        super.setBounds(0, 0, 1920, 1080);
        
        hangman = new JLabel(new ImageIcon(Game_Screen.class.getResource("/images/hangman10.jpg")));
        hangman.setBounds(0, 0, 1920, 1080);
        
        add(hangman, Integer.valueOf(0));
    }
}

游戏中窗格之一的示例

public class Home_Screen extends Game_Screen {
    
    private JLabel title;
    private JLabel score;
    private JButton start;
    
    public Home_Screen() {
        super();
        title = new JLabel("HANGMAN");
        title.setBounds(490, 170, 942, 217);
        title.setFont(new Font("Press Start", Font.PLAIN, 100));
        add(title, Integer.valueOf(1));
        
        score = new JLabel("High Score: 0");
        score.setBounds(635, 330, 470, 67);
        score.setFont(new Font("Press Start", Font.PLAIN, 30));
        add(score, Integer.valueOf(1));
        
        start = new JButton("START");
        start.setBounds(635,400,400,120);
        start.setBorderPainted(false);
        start.setFont(new Font("Press Start", Font.PLAIN, 60));
        add(start, Integer.valueOf(1));
    }
    
    public void addStartButtonListener(ActionListener a) {
        start.addActionListener(a);
    }
}

JFrame Class

public class HangmanGame extends JFrame {
    
    private Home_Screen home;
    private Level_Screen level;
    private Win_Screen win;
    private Lose_Screen lose;
    private Play_Screen play;
    
    public HangmanGame() {
        super("Hangman");
        
        home = new Home_Screen();
        level = new Level_Screen();
        win = new Win_Screen();
        lose = new Lose_Screen();
        play = new Play_Screen();
        add(home);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(1920,1080));
        setLayout(null);
        setVisible(true);


    }
    
    public Home_Screen getHomeScreen() {
        return home;
    }
    
    public Level_Screen getLevelScreen() {
        return level;
    }
    
    public Win_Screen getWinScreen() {
        return win;
    }
    
    public Lose_Screen getLoseScreen() {
        return lose;
    }
    
    public Play_Screen getPlayScreen() {
        return play;
    }
}

Controller class

public class Controller {
    
    private HangmanGame game;
    
    public Controller() {
        //game = g;
        game = new HangmanGame();
        game.getHomeScreen().addStartButtonListener(new startButtonListener());
    }
    
    class startButtonListener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            game.remove(game.getHomeScreen());
            game.add(game.getLevelScreen());
            
        }
        
    }

}

我要在这里和你有点麻烦,坚持住,我相信你会感激的。

首先,Swing 是懒惰的。 当您对组件或布局进行更改时,您需要告诉 Swing 您想要更新内容。

这意味着,当您添加或删除组件时,通常会调用revalidaterepaint 由于您没有大量使用布局管理器,因此您可以离开revalidate

然而。 这里更简单的解决方案是使用CardLayout 这允许您根据需要在视图之间“翻转”。

一,明显的,我对你的方法的问题,是责任的概念。 谁实际上对什么负责。 Controller正在就应该发生的事情做出很多决定,如果您正确使用 controller 可能不是一个坏主意,但是,另一个想法可能是使每个视图都具有一些独立性并使用观察者/代表模式代替。

例如,您并不真正关心Home_Screen “如何”启动,只关心它可以启动。 观察者有兴趣知道“开始”何时发生并采取适当的行动。

你已经用Controller做到了这一点,但我对Controller对组件有深刻理解的想法感到畏缩,这只是我;)。

相反,我希望事情尽可能地愚蠢,所以如果我需要改变事情,并不是每次都完全重写。

相反,在下面的示例中,我在Home_Screen上使用了CardLayout并向HangmanGame提供了一个“委托”,它告诉何时发生“开始”(我不在乎如何,只是它确实如此)然后允许HangmanGame来控制导航。

这通常是一件小事,您可能会争辩说可以使用某种“导航控制器”,但是您需要这样做,这确实暴露了实现细节并且......这是一团糟......:P

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

public class Controller {

    private HangmanGame game;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Controller();
            }
        });
    }

    public Controller() {
        //game = g;
        game = new HangmanGame();
    }

    public class HangmanGame extends JFrame {

        private Home_Screen home;
        private JPanel level;

        public HangmanGame() {
            super("Hangman");

            CardLayout cardLayout = new CardLayout();

            home = new Home_Screen(new HomeDelegate() {
                @Override
                public void startGame() {
                    cardLayout.show(getContentPane(), "level");
                }
            });
            level = new JPanel();
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(new Dimension(1920, 1080));
            setLayout(cardLayout);
            add(home, "home");
            add(level, "level");
            setVisible(true);

        }
    }

    public interface HomeDelegate {

        public void startGame();
    }

    public class Home_Screen extends Game_Screen {

        private JLabel title;
        private JLabel score;
        private JButton start;

        public Home_Screen(HomeDelegate delegate) {
            super();
            title = new JLabel("HANGMAN");
            title.setBounds(490, 170, 942, 217);
            title.setFont(new Font("Press Start", Font.PLAIN, 100));
            add(title, Integer.valueOf(1));

            score = new JLabel("High Score: 0");
            score.setBounds(635, 330, 470, 67);
            score.setFont(new Font("Press Start", Font.PLAIN, 30));
            add(score, Integer.valueOf(1));

            start = new JButton("START");
            start.setBounds(635, 400, 400, 120);
            start.setBorderPainted(false);
            start.setFont(new Font("Press Start", Font.PLAIN, 60));
            add(start, Integer.valueOf(1));

            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    delegate.startGame();
                }
            });
        }
    }

    public class Game_Screen extends JLayeredPane {

        private JLabel hangman;

        public Game_Screen() {
            super();

            hangman = new JLabel(new ImageIcon(getClass().getResource("/images/hangman10.png")));
            hangman.setBounds(0, 0, 1920, 1080);

            add(hangman, Integer.valueOf(0));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(1920, 1080);
        }
    }
}

现在,预计初始加载延迟为 Swing,因为事件调度线程可能需要几秒钟才能启动并完成所有必需的初始化,但一部分“可能”是图像的加载,尽管之前我开始花很多时间担心,我会专注于让你的游戏正常运行

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM