yukashima huksay
yukashima huksay

Reputation: 6248

static way of getting the resource of a file

Update: I want to have the media player static but it does not work if i make is static. Please note that the reason i want mediaPlayer static is that i want to access it from other classes.(the line is commented.) This is my code:

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;
    }
}

Any other fixes to my code will be appreciated. By the way, these are the errors i get:

Exception in thread "Thread-0" java.lang.IllegalStateException: Toolkit not initialized at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273) at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268) at javafx.application.Platform.runLater(Platform.java:83) at javafx.scene.media.Media$_MetadataListener.onMetadata(Media.java:541) at com.sun.media.jfxmediaimpl.MetadataParserImpl.done(MetadataParserImpl.java:120) at com.sun.media.jfxmediaimpl.platform.java.ID3MetadataParser.parse(ID3MetadataParser.java:237) at com.sun.media.jfxmediaimpl.MetadataParserImpl.run(MetadataParserImpl.java:103) Exception in thread "main" java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:122) Caused by: java.lang.IllegalStateException: Toolkit not initialized at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273) at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268) at javafx.application.Platform.runLater(Platform.java:83) at javafx.scene.media.MediaPlayer.init(MediaPlayer.java:515) at javafx.scene.media.MediaPlayer.(MediaPlayer.java:414) at Main.(Main.java:22) ... 3 more

Upvotes: 0

Views: 293

Answers (1)

James_D
James_D

Reputation: 209674

Calling getClass() without an object for context is interpreted the same as any other instance method: this.getClass().

In a static context, you can reference the class with ClassName.class; i.e. you can do

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

However, it is not at all clear in this scenario why you would want these variables to be static; only one instance of an Application subclass should ever be created per JVM instance, and these are inherently properties of that instance.

In the specific example in your (updated) question, I would define a separate class encapsulating the MediaPlayer and the other properties you currently make static. Note that MediaPlayer itself defines a volume property and a muted property. So you could do:

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);
    }
}

Now your Main class can be:

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();
    }

}

and update your GUI and MainMenu classes to have a reference to a 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;
    }
}

Also note that if you expose the actual property objects from SoundPlayer, for example:

public class SoundPlayer {

    private final MediaPlayer mediaPlayer ;

    // ...


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

    // ...
}

then you can simplify some of your code:

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

(Converting the mutedProperty to a soundOnProperty is a little less elegant.)

Upvotes: 4

Related Questions