簡體   English   中英

在javafx.scene.media.MediaPlayer.init使用Media Player時,Java FX空指針異常

[英]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線程上設置場景圖。 有關詳細信息,請參見JFXPanelJavadocs

但是,這是空指針異常附帶的。 我認為這是因為當您從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM