Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向JFrame添加JLayerPane时延迟_Java_Swing_Jlayeredpane - Fatal编程技术网

Java 向JFrame添加JLayerPane时延迟

Java 向JFrame添加JLayerPane时延迟,java,swing,jlayeredpane,Java,Swing,Jlayeredpane,我需要使用Swing在Java中制作一个刽子手游戏。我在photoshop中制作了我的刽子手模型,并使用完整的图像作为背景层,然后使用JlayeredPane将其他组件放置在顶部。然而,当我添加JFrame并打开窗口时,总是有一点延迟。我试图在单击时在JLayeredPane上创建一个添加和删除按钮,但这导致了更大的延迟。任何帮助都将不胜感激 public class Game_Screen extends JLayeredPane { private JLabel hangm

我需要使用Swing在Java中制作一个刽子手游戏。我在photoshop中制作了我的刽子手模型,并使用完整的图像作为背景层,然后使用JlayeredPane将其他组件放置在顶部。然而,当我添加JFrame并打开窗口时,总是有一点延迟。我试图在单击时在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类

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;
    }
}
控制器类

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您希望更新内容

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

不过。这里一个更简单的解决方案是使用
卡片布局
。这允许您根据需要在视图之间“翻转”

我对你的方法有一个突出的问题,那就是责任的概念。谁真正对什么负责。您
Controller
正在对应该发生的事情做出很多决定,如果您正确地使用一个控制器,这可能不是一个坏主意,但是,另一个想法可能是让每个视图都有一些独立性,并改为使用观察者/委托模式

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

您已经用
控制器
完成了这项工作,但我对
控制器
对组件有着深刻的理解这一概念感到畏缩,这就是我;)

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

相反,在下面的示例中,我使用了
HangmanGame
上的
CardLayout
,并向
Home\u屏幕提供了一个“委托”,告知何时发生“启动”(我不在乎它是如何发生的),然后允许
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,因为事件调度线程可能需要几秒钟的时间才能启动,所有必需的初始化也需要几秒钟才能完成,但其中一部分“可能”是映像的加载,尽管在我开始花大量时间担心之前,我只想让你的游戏发挥作用

我要在这里给你点麻烦,坚持住,我相信你会喜欢的

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

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

不过。这里一个更简单的解决方案是使用
卡片布局
。这允许您根据需要在视图之间“翻转”

我对你的方法有一个突出的问题,那就是责任的概念。谁真正对什么负责。您
Controller
正在对应该发生的事情做出很多决定,如果您正确地使用一个控制器,这可能不是一个坏主意,但是,另一个想法可能是让每个视图都有一些独立性,并改为使用观察者/委托模式

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

您已经用
控制器
完成了这项工作,但我对
控制器
对组件有着深刻的理解这一概念感到畏缩,这就是我;)

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

相反,在下面的示例中,我使用了
HangmanGame
上的
CardLayout
,并向
Home\u屏幕提供了一个“委托”,告知何时发生“启动”(我不在乎它是如何发生的),然后允许
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,因为事件调度线程可能需要几秒钟的时间才能启动,所有必需的初始化也需要几秒钟才能完成,但其中一部分“可能”是映像的加载,尽管在我开始花大量时间担心之前,我会专注于让你的游戏正常运行

我会使用
卡片布局
在主/关卡屏幕之间切换我能将布局添加到JFrame吗?我还可以将LayeredPane作为组件使用布局吗?
CardLayout
将添加到主组件,是的,可以在布局管理器中使用
JLayeredPane
。我个人的做法是制作一系列刽子手的图像,然后简单地更改
JLabel
图标,这可能会更简单,我会尝试一下,谢谢。我有一系列的刽子手图像,我只是还没有添加它们,我只使用了一个图像t