[英]Java FX Null Pointer Exception when using Media Player at javafx.scene.media.MediaPlayer.init
在啟動MediaPlayer的Media塊中沒有空字段
我對此進行了廣泛的研究,但沒有發現任何可以解釋此錯誤的信息。
我正在為一個班級項目構建Java Swing應用程序,並嘗試使用JFX面板和媒體播放器來托管和播放多個mp4視頻。 我已經成功地完成了一次工作,但是當我再次回到窗口時,我遇到了錯誤。
com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer.playerSetBalance(Unknown Source)處的com.sun.media.jfxmediaimpl.NativeMediaPlayer.setBalance(javafx.scene.media.MediaPlayer)處的java.lang.NullPointerException。 javafx.scene.media.MediaPlayer上的init(未知源).project.screens.TutorialPlayerScreen.initMediaPlayer(TutorialPlayerScreen.java:156)處project.screens.TutorialPlayerScreen.init(TutorialPlayerScreen.java:122)處的init(未知源) .projects.buttons.PreKModuleSelectTutorialButtons $ Button $ 7.doAction。 ContentPane.notifiyObserver(ContentPane.java:457)在project.tools.ContentPane $ 1.mousePressed(ContentPane.java:272)在java.awt.Component.processMouseEvent(未知源)在javax.swing.JComponent.processMouseEvent(未知源)在java.awt.Component.pro cessEvent(未知源),位於java.awt.Container.processEvent(未知源),位於java.awt.Container.dispatchEventImpl(未知源),java.awt.Component.dispatchEventImpl(未知源) java.awt.LightweightDispatcher.retargetMouseEvent的來源不明(java.awt.LightweightDispatcher.processMouseEvent的java.awt.LightweightDispatcher.dispatchEvent的來源不明(java.awt.Container.dispatchEventImpl的來源不明) )處java.awt.Window.dispatchEventImpl(未知源)處java.awt.EventQueue.dispatchEventImpl(未知源)處java.awt.EventQueue.access $ 500(未知源)在java.awt.EventQueue $ 3.run(未知源)在java.awt.EventQueue $ 3.run(未知源)在java.security.AccessController.doPrivileged(本機方法)在java.security.ProtectionDomain $ 1.doIntersectionPrivilege(未知源) )在java.security.ProtectionDomain $ 1.doIntersectionPrivilege(Un java.awt.EventQueue $ 4.run(未知源)java.awt.EventQueue $ 4.run(未知源)java.security.AccessController.doPrivileged(本機方法)java.security.ProtectionDomain $ 1.doIntersectionPrivilege (未知源)在java.awt.EventQueue.dispatchEvent(未知源)在java.awt.EventDispatchThread.pumpOneEventForFilters(未知源)在java.awt.EventDispatchThread.pumpEventsForFilter(未知源)在java.awt.EventDispatchThread.pumpEventsForHierarchy(未知Source)(java.awt.EventDispatchThread.pumpEvents(未知源)java.awt.EventDispatchThread.pumpEvents(未知源)java.awt.EventDispatchThread.run(未知源)
這是我用來啟動JFX媒體的代碼:
'//媒體播放器支持私有組mediaRoot; 私人場景媒體場景;
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);
}'
我試圖在離開屏幕之前清理使用的內存。
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();
}
任何幫助或評論將不勝感激! 謝謝!
您的代碼中存在線程問題,需要解決。 具體來說,您必須創建FX UI組件並在FX Application線程上設置場景圖。 有關詳細信息,請參見JFXPanel
的Javadocs 。
但是,這是空指針異常附帶的。 我認為這是因為當您從UI中完全刪除JFXPanel
時,FX工具包正在關閉。 為了防止這種情況,只需致電
Platform.setImplicitExit(false);
首次初始化應用程序時。 (可以從任何線程安全地調用此方法。)
這是外觀類似的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);
}
}
這可能不是導致NullPointerException的問題,但是您需要在不同的線程上進行不同的方法調用。 特別是,必須在AWT事件分配線程上調用new JFXPanel(),而其他initMediaPlayer則需要在FX Application線程上調用。 請參閱JFXPanel javadocs。 (雖然這可能不是問題的原因,但可以想象是這樣的。)– James_D
這樣就解決了問題。
我將JFX Panel設置為由主窗口管理,並且永遠不會超出范圍。 為了僅在我想要的屏幕上解決可見性問題,我將功能更改為這些...
public void tearDown(){
this.mediaPanel.getMediaPanel().setVisible(false);
this.VideoPlayer.stop();
}
和
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);
}
感謝所有提供幫助的人!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.