更新:
我想让媒体播放器是静态的,但是如果我制作的是静态的,它将无法正常工作。
请注意,我希望mediaPlayer静态的原因是我想从其他类访问它。(该行已注释。)
这是我的代码:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.net.URL;

public class Main extends Application {
    static boolean isSoundOn = false;
    static double soundVolume = .5;
    MediaPlayer mediaPlayer = new MediaPlayer(new Media(Main.class.getResource("song.mp3").toString()));

public static void main(String[] args) {
    Application.launch(args);
}

@Override
public void start(Stage primaryStage) {
    mediaPlayer.play();
    primaryStage.setTitle("duet by what");

//        primaryStage.setFullScreen(true);


    //Group gamePaused = new Group();
    //Scene _gamePaused = new Scene(gamePaused, 1200, 700);
    //Group gameOver = new Group();
    //Scene _gameOver = new Scene(gameOver, 1200, 700);
    //Group game = new Group();
    //Scene _game = new Scene(game, 1200, 700);

    GUI gui = new GUI();
    primaryStage.setScene(gui.getMainMenu().getScene());
    primaryStage.show();
}
}

class GUI {
    private MainMenu mainMenu = new MainMenu();



 public class MainMenu {
        private Scene scene;

        private MainMenu() {
            VBox vBox = new VBox();
            scene = new Scene(vBox, 400, 500);
            scene.getStylesheets().add("stylesheet.css");

            Label info = new Label(
                    "welcome the the what version\n" +
                            "of the well known Duet game!\n\n" +
                            "press \"I wanna play!\" to begin the game.\n\n" +
                            "please note that you can change\n" +
                            "the sound settings.");
            info.setId("info");
            vBox.getChildren().add(info);

            Button startGame = new Button("i wanna play right now!");
            startGame.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    System.out.println("game started!");
                }
            });
            vBox.getChildren().add(startGame);

            Label highScore = new Label("__highScore should be added here__");
            highScore.setId("highScore");
            vBox.getChildren().add(highScore);

            Button quitGame = new Button("get me out of this game!");
            quitGame.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    System.out.println("game quitted!");
                }
            });
            vBox.getChildren().add(quitGame);

            CheckBox soundOn = new CheckBox("soundOn?");
            Tooltip tooltip = new Tooltip("if this box is checked, music will be played!");
            tooltip.setFont(new Font("Arial", 16));
            soundOn.setTooltip(tooltip);
            soundOn.selectedProperty().addListener(new ChangeListener<Boolean>() {
                public void changed(ObservableValue<? extends Boolean> ov,
                                    Boolean old_val, Boolean new_val) {
                    Main.isSoundOn = soundOn.isSelected();
                    System.out.println(Main.isSoundOn);
                }
            });
            vBox.getChildren().add(soundOn);

            HBox changeVolumeWrapper = new HBox();
            changeVolumeWrapper.setId("hBox");
            Label sliderLabel = new Label("sound volume: ");
            changeVolumeWrapper.getChildren().add(sliderLabel);

            Slider soundVolume = new Slider(0, 1, .5);
            soundVolume.valueProperty().addListener(new ChangeListener<Number>() {
                public void changed(ObservableValue<? extends Number> ov,
                                    Number old_val, Number new_val) {
                    Main.soundVolume = new_val.doubleValue();
                    //Main.mediaPlayer.setVolume(Main.soundVolume);  here is why i need media player static.
                    System.out.printf("%.2f\n", Main.soundVolume);
                }
            });
            changeVolumeWrapper.getChildren().add(soundVolume);
            vBox.getChildren().add(changeVolumeWrapper);
        }

        public Scene getScene() {
            return scene;
        }
    }

    public MainMenu getMainMenu() {
        return mainMenu;
    }
}


我的代码的任何其他修复将不胜感激。
顺便说一下,这些是我得到的错误:


  线程“ Thread-0”中的异常java.lang.IllegalStateException:
  工具包未在初始化
  com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
    在
  com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
    在javafx.application.Platform.runLater(Platform.java:83)在
  javafx.scene.media.Media $ _MetadataListener.onMetadata(Media.java:541)
    在
  com.sun.media.jfxmediaimpl.MetadataParserImpl.done(MetadataParserImpl.java:120)
    在
  com.sun.media.jfxmediaimpl.platform.java.ID3MetadataParser.parse(ID3MetadataParser.java:237)
    在
  com.sun.media.jfxmediaimpl.MetadataParserImpl.run(MetadataParserImpl.java:103)
  线程“主”中的异常java.lang.ExceptionInInitializerError在
  java.lang.Class.forName0(本机方法),位于
  java.lang.Class.forName(Class.java:264)在
  com.intellij.rt.execution.application.AppMain.main(AppMain.java:122)
  原因:java.lang.IllegalStateException:工具箱未初始化
    在
  com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
    在
  com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
    在javafx.application.Platform.runLater(Platform.java:83)在
  javafx.scene.media.MediaPlayer.init(MediaPlayer.java:515)在
  javafx.scene.media.MediaPlayer。(MediaPlayer.java:414)在
  Main。(Main.java:22)...还有3个

最佳答案

在没有对象作为上下文的情况下调用getClass()的解释与其他任何实例方法:this.getClass()相同。

在静态上下文中,可以使用ClassName.class引用该类。即你可以做

static URL resource = Main.class.getResource("a.mp3");


但是,在这种情况下根本不清楚为什么要让这些变量是静态的。每个JVM实例只能创建一个Application子类的实例,而这些实例本质上是该实例的属性。

在您的(更新的)问题的特定示例中,我将定义一个单独的类,封装MediaPlayer和您当前使其静态的其他属性。请注意,MediaPlayer本身定义了volume属性和muted属性。因此,您可以执行以下操作:

public class SoundPlayer {

    private final MediaPlayer mediaPlayer ;

    public SoundPlayer(URL url) {
        this.mediaPlayer = new MediaPlayer(new Media(url));
    }

    public void play() {
        mediaPlayer.play();
    }

    public double getVolume() {
        return mediaPlayer.getVolume();
    }

    public void setVolume(double volume) {
        mediaPlayer.setVolume(volume);
    }

    public boolean isSoundOn() {
        return ! mediaPlayer.isMuted();
    }

    public void setSoundOn(boolean soundOn) {
        mediaPlayer.setMuted(! soundOn);
    }
}


现在,您的Main类可以是:

public class Main extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        SoundPlayer soundPlayer = new SoundPlayer(getClass().getResource("song.mp3"));
        soundPlayer.play();


        primaryStage.setTitle("duet by Aran Mohyeddin");

        GUI gui = new GUI(soundPlayer);

        primaryStage.setScene(gui.getMainMenu().getScene());
        primaryStage.show();
    }

}


并更新您的GUIMainMenu类以引用SoundPlayer

public class MainMenu {
        private Scene scene;

        private final SoundPlayer soundPlayer ;

        private MainMenu(SoundPlayer soundPlayer) {

            this.soundPlayer = soundPlayer ;

            // existing code omitted...

            CheckBox soundOn = new CheckBox("soundOn?");
            Tooltip tooltip = new Tooltip("if this box is checked, music will be played!");
            tooltip.setFont(new Font("Arial", 16));
            soundOn.setTooltip(tooltip);
            soundOn.selectedProperty().addListener(new ChangeListener<Boolean>() {
                public void changed(ObservableValue<? extends Boolean> ov,
                                    Boolean old_val, Boolean new_val) {

                    soundPlayer.setSoundOn(new_val);
                }
            });

            // ...


            Slider soundVolume = new Slider(0, 1, .5);
            soundVolume.valueProperty().addListener(new ChangeListener<Number>() {
                public void changed(ObservableValue<? extends Number> ov,
                                    Number old_val, Number new_val) {

                    soundPlayer.setVolumn(new_val.doubleValue());
                    System.out.printf("%.2f\n", Main.soundVolume);
                }
            });
            changeVolumeWrapper.getChildren().add(soundVolume);
            vBox.getChildren().add(changeVolumeWrapper);
        }

        public Scene getScene() {
            return scene;
        }
    }

    public MainMenu getMainMenu() {
        return mainMenu;
    }
}


还请注意,如果您从SoundPlayer公开实际的属性对象,例如:

public class SoundPlayer {

    private final MediaPlayer mediaPlayer ;

    // ...


    public DoubleProperty volumeProperty() {
        return mediaPlayer.volumeProperty();
    }

    // ...
}


那么您可以简化一些代码:

    Slider soundVolume = new Slider(0, 1, .5);
    // instead of the listener, just do:
    soundPlayer.volumeProperty().bindBidirectional(soundVolume.valueProperty());


(将mutedProperty转换为soundOnProperty不太优雅。)

09-04 06:23
查看更多