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