2016-06-07 122 views
0

更新: 我希望媒體播放器是靜態的,但如果我製作是靜態的,它不起作用。 請注意,我想媒體播放靜態的原因是,我想從其他類訪問它(行註釋)。 這是我的代碼:獲取文件資源的靜態方法

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

任何其他修復我的代碼可以理解的。 順便說一句,這些都是錯誤的,我得到:

異常在線程「線程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) at com.sun.media.jfxmediaimpl.MetadataParserImpl.done(MetadataParserImpl.java:120) at com.sun.media.jfxmediaimpl.platform.java.ID3MetadataParser.parse(ID3MetadataParser.java:237) 在 com.sun.media.jfxmediaimpl.MetadataParserImpl.run(MetadataParserImpl.java:103) 異常在線程「主「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) 引起:java.lang.IllegalStateException:工具包不 com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273) 在 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 。)在 主(Main.java:22)... 3更

+2

您的MediaPlayer並不需要是靜態的在這裏。請參閱下面的James_D的答案。儘可能避免使用靜態變量。 – ManoDestra

+0

是的BC這不是我的整個代碼我想從其他類訪問這個媒體播放器:) –

+0

正如我下面發佈,'靜態'與無障礙/可見性無關 –

回答

4
而不

爲上下文對象調用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()); 

(轉換的mutedPropertysoundOnProperty是有點不太優雅。)

+0

非常感謝!以及我只是想訪問其他類的媒體播放器沒有封裝和傳遞主要bc的實例我認爲媒體播放器也應該是最後的 –

+0

靜態與訪問字段無關,並且完全獨立於字段是否是最終的。爲了避免執行正確的封裝,製作變量靜態是非常糟糕的做法。 –