java为什么调用不同类的主方法不能正常工作?
我正在写一个游戏。游戏在运行时播放背景音乐。这很好用,我决定添加一个主菜单,因为它们是这个游戏的三种类型:
单人游戏
两人游戏
在线
当我单独运行这些类(显然,它们有自己的主要方法)时,它们工作得非常好。但是,在我的欢迎菜单类中,它负责主菜单(所有必要的导入都在那里,只是这里没有显示):
public class WelcomeMenu implements ActionListener {
public void setButtonBG(JButton button, String imgPath) throws IOException //this method is reponsible for setting images to their corresponding JButton(s)
{
BufferedImage img = ImageIO.read(ClassLoader.getSystemResource(imgPath));
ImageIcon sp = new ImageIcon(img);
button.setIcon(sp);
button.setBorderPainted(false);
}
private JFrame welcomeWindow = new JFrame("Tic-Tac-Toe");
private JButton singlePlayerButton = new JButton();
private JButton twoPlayerButton = new JButton();
private JButton onlineButton = new JButton();
public WelcomeMenu() throws IOException
{
//START OF CONSTRUCTOR
//Main window is being sized, default way to close, and internal layout
welcomeWindow.setSize(600, 420);
welcomeWindow.setLayout(new CardLayout());
//Object res = this.getClass().getResource("/");
//System.out.println(res);
BufferedImage bf = ImageIO.read(ClassLoader.getSystemResource("images/mainMenuBG.jpg"));
welcomeWindow.setContentPane(new backImage(bf)); // adding created component to the JFrame using the backImage class
welcomeWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
welcomeWindow.setLocationRelativeTo(null);
welcomeWindow.setResizable(false);
welcomeWindow.setVisible(true);
//setting the icon
try
{
java.net.URL url = ClassLoader.getSystemResource("images/icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
welcomeWindow.setIconImage(img);
}
catch(NullPointerException n)
{
System.out.println("Image could not be fetched.");
}
//adding custom buttons
//ImageIcon singlePlayer = new ImageIcon("images/singlePlayerButton.jpg");
//setting sizes
singlePlayerButton.setSize(387, 72);
twoPlayerButton.setSize(387, 72);
onlineButton.setSize(387, 72);
//setting background images to buttons
setButtonBG(singlePlayerButton, "images/sPlayerButton.jpg");
setButtonBG(twoPlayerButton, "images/tPlayerButton.jpg");
setButtonBG(onlineButton, "images/mPlayerButton.jpg");
//adding listeners
singlePlayerButton.addActionListener(this);
twoPlayerButton.addActionListener(this);
onlineButton.addActionListener(this);
//adding the custom buttons
welcomeWindow.add(singlePlayerButton);
welcomeWindow.add(twoPlayerButton);
welcomeWindow.add(onlineButton);
//setting locations and visibility
singlePlayerButton.setLocation(110, 90);
singlePlayerButton.setVisible(true);
twoPlayerButton.setLocation(110, 182);
twoPlayerButton.setVisible(true);
onlineButton.setLocation(110, 274);
onlineButton.setVisible(true);
//END OF CONSTRUCTOR
}
public static TicTacToeTP spg;
//All actions are done here
@Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == singlePlayerButton)
{
System.out.println("<LOG> SINGLE PLAYER GAME REQUESTED");
JOptionPane.showMessageDialog(welcomeWindow, "This game mode has not been implemented yet.");
}
if(e.getSource() == twoPlayerButton)
{
System.out.println("<LOG> TWO PLAYER GAME REQUESTED");
try
{
//spg = new TicTacToeTP("images/black-squareMod_RED.jpg");
//spg.playBackgroundSong();
TicTacToeTP.main(null);
}
catch(IOException io)
{
System.out.println("IO EXCEPTION!");
}
welcomeWindow.setVisible(false);
welcomeWindow.dispose();
}
if(e.getSource() == onlineButton)
{
System.out.println("<LOG> ONLINE GAME REQUESTED");
JOptionPane.showMessageDialog(welcomeWindow, "This game mode has not been implemented yet.");
}
}
public static void main(String[] args) throws IOException
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)
{
}
}
});
new WelcomeMenu();
}
}
。。。例如,如果我单击双播放器按钮,它将只播放音频。我的其他组件都没有加载。只是一个空的JFrame。请注意,在actionPerformed()方法中,我尝试了两种方法。main(null)和(注释掉,现在)实例化一个新的TicTacToeTP对象并调用playBackgroundSong()方法。如果我消除了这个方法调用,只实例化对象,它工作得很好——但没有音乐
为什么会发生这种情况,我该如何解决
以下是playBackgroundSong()方法:
private Player p = null;
//private InputStream fis = null;
public void playBackgroundSong() //responsible for playing background music
{
//PausablePlayer p = null;
InputStream fis = null;
ArrayList<InputStream> stream = new ArrayList<InputStream>(); //this ArrayList contains multiple audio files that the method will loop through >> defined below
stream.add(ClassLoader.getSystemResourceAsStream("resources/01 Intro.mp3"));
stream.add(ClassLoader.getSystemResourceAsStream("resources/Basic space - The XX - Instrumental.mp3"));
stream.add(ClassLoader.getSystemResourceAsStream("resources/Mirrors [ Upbeat Electronic Instrumental ] Spence Mills HQ Free Beat Download 2012.mp3"));
stream.add(ClassLoader.getSystemResourceAsStream("resources/Static [ Aggressive Dark Pop Hip Hop Rap Instrumental ] Spence Mills Free Beat Download Link 2012 HD.mp3"));
stream.add(ClassLoader.getSystemResourceAsStream("resources/System Shock 2 soundtrack Med Sci 1.mp3"));
stream.add(ClassLoader.getSystemResourceAsStream("resources/System Shock 2 Soundtrack Ops 2.mp3"));
stream.add(ClassLoader.getSystemResourceAsStream("resources/01 Intro.mp3"));
Collections.shuffle(stream);
for(int i = 0; i < stream.size(); i++)
{
try
{
fis = stream.get(i);
}
catch (NullPointerException ex)
{
Logger.getLogger(TicTacToeTP.class.getName()).log(Level.SEVERE, null, ex);
}
try
{
p = new Player(fis);
}
catch (JavaLayerException ex)
{
Logger.getLogger(TicTacToeTP.class.getName()).log(Level.SEVERE, null, ex);
}
try
{
p.play();
}
catch (JavaLayerException ee)
{
Logger.getLogger(TicTacToeTP.class.getName()).log(Level.SEVERE, null, ee);
}
}
playBackgroundSong();
}
# 1 楼答案
您似乎正在Swing事件调度线程或EDT上播放一段长时间运行的代码。这个线程负责绘制GUI、交互和响应用户输入,如果它被占用,程序基本上会冻结。当您在基本上脱离Swing事件线程的main方法中调用此方法时,这可能不是问题,但在事件分派线程上专门调用它时,这是问题。一个可能的解决方案是:在背景线中播放音乐。一个SwingWorker可能对你很有用,关于这些和EDT的使用,有很多不错的教程。谷歌“Concurrency in Swing”,看看什么可能是第一个点击更多
顺便说一句:您通常不想调用另一个类的main方法。而是创建另一个类的实例并使用它
编辑您声明:
实际上,你可以做得更简单。由于您不需要等待
playBackgroundSong()
的结果,您可以在自己的简单线程中调用它,只需将其包装在Runnable中,然后将其放入线程中: