问题
There are no null fields in the Media block that launch the MediaPlayer
I have researched this extensively and have found nothing to explain this error.
I am building a Java Swing application for a class project and am attempting to use the JFX panel and media player to host and play several mp4 videos. I have successfully got it working one time through however when I come back to the window again I run into the error.
java.lang.NullPointerException at com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer.playerSetBalance(Unknown Source) at com.sun.media.jfxmediaimpl.NativeMediaPlayer.setBalance(Unknown Source) at javafx.scene.media.MediaPlayer.init(Unknown Source) at javafx.scene.media.MediaPlayer.(Unknown Source) at project.screens.TutorialPlayerScreen.initMediaPlayer(TutorialPlayerScreen.java:156) at project.screens.TutorialPlayerScreen.init(TutorialPlayerScreen.java:122) at project.screens.TutorialPlayerScreen.(TutorialPlayerScreen.java:113) at project.buttons.PreKModuleSelectTutorialButtons$Button$7.doAction(PreKModuleSelectTutorialButtons.java:225) at project.screens.PreKModuleSelect.clicked(PreKModuleSelect.java:359) at project.tools.ContentPane.notifiyObserver(ContentPane.java:457) at project.tools.ContentPane$1.mousePressed(ContentPane.java:272) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$500(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
Here is the code I used to start the JFX media:
' //Media Player Support private Group mediaRoot; private Scene mediaScene;
private Media tutorialVideo;
private MediaPlayer VideoPlayer;
private MediaView mediaViewer;
private JFXPanel fxPanel;
private int jfxPanelHeight = 394;//525;
private int jfxPanelWidth = 700;//700;
private void initMediaPlayer() throws IOException {
this.fxPanel = new JFXPanel(); //initializes JFX variables
fxPanel.setSize(this.jfxPanelWidth ,this.jfxPanelHeight);
//Add JFX Panel component to the Main Window
int padding = ((mainWindow.getPreferredSize().width - this.jfxPanelWidth) / 2);
mainWindow.addLayer(fxPanel, MEDIA_LAYER, padding, 125);
//Initialize FX Panel
this.mediaRoot = new Group();
this.mediaScene = new Scene(this.mediaRoot, 0, 0);
//Open/prepare the file
//String tutorialFilePath = new File("").getAbsolutePath() + DIRECTORY_PATH + "Tutorial.mp4";
String tutorialFilePath = new File("").getAbsolutePath() + MEDIA_PATH + this.observer.getName() +"Tutorial.mp4";
File mediaFile = new File(tutorialFilePath);
this.tutorialVideo = new Media(mediaFile.toURI().toString());
//Create the media player
this.VideoPlayer = new MediaPlayer(this.tutorialVideo); //Error here
this.VideoPlayer.setAutoPlay(false);
this.mediaViewer = new MediaView(this.VideoPlayer);
this.mediaViewer.setFitHeight(this.jfxPanelHeight);
this.mediaViewer.setFitWidth(this.jfxPanelWidth);
((Group)this.mediaScene.getRoot()).getChildren().add(this.mediaViewer);
fxPanel.setScene(this.mediaScene);
}'
I attempt to clean up the used memory before leaving the screen.
public void tearDown(){
//Stop the JFX Player and Remove
this.mainWindow.removeLayer(this.fxPanel);
this.VideoPlayer.stop();
this.VideoPlayer.dispose();
this.fxPanel.removeAll();
this.mediaRoot.getChildren().removeAll();
this.mediaRoot = null;
this.mediaScene = null;
this.mediaViewer = null;
this.tutorialVideo = null;
this.VideoPlayer = null;
this.fxPanel = null;
}
private JLayeredPane contentPane; //The content pane of this JFrame.
public void removeLayer(JComponent component) {
contentPane.remove(component);
contentPane.revalidate();
contentPane.repaint();
}
Any help or comment would be much appreciated! Thank you!
回答1:
You have threading issues in your code, which need to be fixed. Specifically, you must create FX UI components and set up the scene graph on the FX Application thread. See the Javadocs for JFXPanel for details.
This is incidental to the Null Pointer Exception, however. What I think is causing that is that the FX toolkit is closing down when you remove the JFXPanel
completely from the UI. In order to prevent this, just call
Platform.setImplicitExit(false);
when you first initialize your application. (This method is safe to call from any thread.)
Here's a similar-looking SSCCE:
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MediaPlayerInSwing {
private static final String MEDIA_URL = "http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv" ;
private JFrame window ;
private JFXPanel jfxPanel ;
private Media media ;
private MediaPlayer player ;
private MediaView mediaView ;
private BorderPane root ;
private Scene scene ;
private Button button ;
// create on AWT Event Dispatch Thread
public MediaPlayerInSwing() {
Platform.setImplicitExit(false);
initGUI();
}
private void initGUI() {
window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new BorderLayout());
JPanel controls = new JPanel();
controls.setLayout(new FlowLayout());
button = new Button("Show video");
controls.add(button);
button.addActionListener(e -> {
if (jfxPanel == null) {
showVideo();
} else {
tearDownVideo();
}
});
window.add(controls, BorderLayout.SOUTH);
window.setSize(600, 480);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
private void showVideo() {
jfxPanel = new JFXPanel();
Platform.runLater(() -> {
media = new Media(MEDIA_URL);
player = new MediaPlayer(media);
player.play();
mediaView = new MediaView(player);
root = new BorderPane(mediaView);
scene = new Scene(root, 600, 400);
jfxPanel.setScene(scene);
});
window.add(jfxPanel, BorderLayout.CENTER);
button.setLabel("Hide video");
}
private void tearDownVideo() {
window.remove(jfxPanel);
Platform.runLater(() -> {
player.stop();
player.dispose();
player = null ;
mediaView = null ;
root = null ;
jfxPanel.setScene(null);
scene = null ;
SwingUtilities.invokeLater(() -> {
jfxPanel = null ;
// force window to repaint...
window.getRootPane().repaint();
});
});
button.setLabel("Show video");
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(MediaPlayerInSwing::new);
}
}
回答2:
This might not be the issue causing the NullPointerException, but you need to make the different method calls on different threads. In particular, new JFXPanel() must be called on the AWT event dispatch thread, whereas the rest of initMediaPlayer needs to be called on the FX Application Thread. See the JFXPanel javadocs. (And while this might not be the cause of the problem, it is conceivable that it is.) – James_D
This solved the problem.
I set the JFX Panel to be managed by the main window and never goes out of scope. To solve the issue of visibility only on the screens that I want it to I changed the functions to these...
public void tearDown(){
this.mediaPanel.getMediaPanel().setVisible(false);
this.VideoPlayer.stop();
}
and
private void initMediaPlayer() throws IOException {
this.mediaPanel.getMediaPanel().setVisible(true);
//Initialize FX Panel
this.mediaRoot = new Group();
this.mediaScene = new Scene(this.mediaRoot, 0, 0);
//Open/prepare the file
//String tutorialFilePath = new File("").getAbsolutePath() + DIRECTORY_PATH + "Tutorial.mp4";
String tutorialFilePath = new File("").getAbsolutePath() + MEDIA_PATH + this.observer.getName() +"Tutorial.mp4";
File mediaFile = new File(tutorialFilePath);
this.tutorialVideo = new Media(mediaFile.toURI().toString());
//Create the media player
this.VideoPlayer = new MediaPlayer(this.tutorialVideo); //Error here
this.VideoPlayer.setAutoPlay(false);
this.mediaViewer = new MediaView(this.VideoPlayer);
this.mediaViewer.setFitHeight(this.mediaPanel.getPanelHeight());
this.mediaViewer.setFitWidth(this.mediaPanel.getPanelWidth());
((Group)this.mediaScene.getRoot()).getChildren().add(this.mediaViewer);
this.mediaPanel.getMediaPanel().setScene(this.mediaScene);
}
Thanks to everyone who helped!
来源:https://stackoverflow.com/questions/29885065/java-fx-null-pointer-exception-when-using-media-player-at-javafx-scene-media-med