【问题标题】:Why does calling the main method of a different class not work correctly?为什么调用不同类的主要方法不能正常工作?
【发布时间】:2013-05-17 23:37:59
【问题描述】:

我正在编写游戏。游戏在运行时播放背景音乐。这很好用,我决定添加一个主菜单,因为它们是这个游戏的三种类型:

  • 单人游戏

  • 两个玩家

  • 在线

当我单独运行这些类(它们有自己的主要方法 - 显然)时,它们工作得非常好。但是,在我的 Welcome Menu 类中,它负责主菜单(所有必要的导入都在那里,只是这里没有显示):

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() 方法中,我尝试了 TicTacToeTP.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();
    }

【问题讨论】:

  • 我理解正确吗?您是在尝试调用另一个类的 main 方法吗?
  • 是的,但运行不正常。
  • 好吧...你为什么调用main方法而不是正常实例化类? main 方法不应该被调用。它们更像是“开始”按钮。如果你需要一个类的功能,你只需制作对象。我了解您已尝试实例化,但没有音乐。你的程序有缺陷。不要调用其他类的 main 方法。

标签: java swing class


【解决方案1】:

您似乎在 Swing 事件调度线程或 EDT 上播放一段长时间运行的代码 playBackgroundSong()。该线程负责绘制 GUI 并交互和响应用户输入,如果它被占用,程序基本上会冻结。当您在 main 方法中调用此方法时,这可能不是问题 - 基本上是在 Swing 事件线程之外,但在事件调度线程上专门调用它时会出现问题。一个可能的解决方案:在后台线程中播放音乐。 SwingWorker 可能适合您,并且有关于使用这些和 EDT 的不错的教程。谷歌“Concurrency in Swing”,看看什么可能是第一个点击更多。

顺便说一句:您通常不想调用另一个类的 main 方法。而是创建另一个类的实例并使用它。


编辑您说:

谢谢。看这部分:docs.oracle.com/javase/tutorial/uiswing/concurrency/simple.html 似乎解释了我想要做什么,对吗?顺便说一句,我正在阅读所有内容

其实你可以更简单。由于您不等待来自playBackgroundSong() 的结果,因此您可能只需将其包装在 Runnable 中,然后将其放入线程中即可在其自己的简单线程中调用它:

new Thread(new Runnable() {
  public void run() {
    playBackgroundSong();
  }
}).start();

【讨论】:

  • 这很有道理,但你能解释一下我如何在单独的线程中播放音频吗?我只是将方法放在不同的类中吗?我不太明白什么是线程。
  • 再一次,请看一下Concurrency in Swing,因为它会解释很多细节,因为您需要做一些阅读才能完全理解这一点。
  • 谢谢。看这部分:docs.oracle.com/javase/tutorial/uiswing/concurrency/simple.html 似乎解释了我想要做什么,对吗?顺便说一句,我正在阅读所有内容。
  • 谢谢一百万。那工作得很好。我真的很感激你的洞察力。另外,我现在对线程的理解好多了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 1970-01-01
  • 2021-09-01
  • 1970-01-01
  • 2017-02-06
  • 2013-05-21
  • 1970-01-01
相关资源
最近更新 更多