在javafx.scene.media.MediaPlayer.init

时间:2015-04-26 23:53:51

标签: java swing javafx

媒体块中没有启动MediaPlayer的空字段

我对此进行了广泛的研究,并没有发现任何可以解释这个错误的内容。

我正在为一个类项目构建一个Java Swing应用程序,并且我正在尝试使用JFX面板和媒体播放器来托管和播放几个mp4视频。我已经成功地让它工作了一段时间但是当我再次回到窗口时我遇到了错误。

  

java.lang.NullPointerException at   com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer.playerSetBalance(未知   来源)at   com.sun.media.jfxmediaimpl.NativeMediaPlayer.setBalance(未知   来源)在javafx.scene.media.MediaPlayer.init(未知来源)at   javafx.scene.media.MediaPlayer。(未知来源)at   project.screens.TutorialPlayerScreen.initMediaPlayer(TutorialPlayerScreen.java:156)     在   project.screens.TutorialPlayerScreen.init(TutorialPlayerScreen.java:122)     在   project.screens.TutorialPlayerScreen。(TutorialPlayerScreen.java:113)     在   project.buttons.PreKModuleSelectTutorialButtons $按钮$ 7.doAction(PreKModuleSelectTutorialButtons.java:225)     在   project.screens.PreKModuleSelect.clicked(PreKModuleSelect.java:359)     在project.tools.ContentPane.notifiyObserver(ContentPane.java:457)     在project.tools.ContentPane $ 1.mousePressed(ContentPane.java:272)at   java.awt.Component.processMouseEvent(未知来源)at   javax.swing.JComponent.processMouseEvent(未知来源)at   java.awt.Component.processEvent(未知来源)at   java.awt.Container.processEvent(未知来源)at   java.awt.Component.dispatchEventImpl(未知来源)at   java.awt.Container.dispatchEventImpl(未知来源)at   java.awt.Component.dispatchEvent(未知来源)at   java.awt.LightweightDispatcher.retargetMouseEvent(未知来源)at   java.awt.LightweightDispatcher.processMouseEvent(未知来源)at   java.awt.LightweightDispatcher.dispatchEvent(未知来源)at   java.awt.Container.dispatchEventImpl(未知来源)at   java.awt.Window.dispatchEventImpl(未知来源)at   java.awt.Component.dispatchEvent(未知来源)at   java.awt.EventQueue.dispatchEventImpl(未知来源)at   java.awt.EventQueue.access $ 500(未知来源)at   java.awt.EventQueue $ 3.run(未知来源)at   java.awt.EventQueue $ 3.run(未知来源)at   java.security.AccessController.doPrivileged(Native Method)at   java.security.ProtectionDomain $ 1.doIntersectionPrivilege(未知   来源)at   java.security.ProtectionDomain $ 1.doIntersectionPrivilege(未知   来自)java.awt.EventQueue $ 4.run(未知来源)at   java.awt.EventQueue $ 4.run(未知来源)at   java.security.AccessController.doPrivileged(Native Method)at   java.security.ProtectionDomain $ 1.doIntersectionPrivilege(未知   来自)java.awt.EventQueue.dispatchEvent(未知来源)at   java.awt.EventDispatchThread.pumpOneEventForFilters(未知来源)     at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)     在java.awt.EventDispatchThread.pumpEventsForHierarchy(未知   来自java.awt.EventDispatchThread.pumpEvents(未知来源)     at java.awt.EventDispatchThread.pumpEvents(Unknown Source)at   java.awt.EventDispatchThread.run(未知来源)

以下是我用来启动JFX媒体的代码:

'//媒体播放器支持     私人集团mediaRoot;     私人场景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);
}'

我尝试在离开屏幕前清理用过的内存。

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

非常感谢任何帮助或评论!谢谢!

2 个答案:

答案 0 :(得分:2)

您的代码中存在线程问题,需要修复。具体来说,您必须创建FX UI组件并在FX Application线程上设置场景图。有关详细信息,请参阅Javadocs for JFXPanel

然而,这是Null Pointer Exception的偶然事件。我认为导致这一点的是,当您从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);
    }
}

答案 1 :(得分:0)

  

这可能不是导致NullPointerException的问题,但是你   需要在不同的线程上进行不同的方法调用。在   特别是,必须在AWT事件调度上调用新的JFXPanel()   线程,而initMediaPlayer的其余部分需要在上面调用   FX应用程序线程。请参阅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);
}

感谢所有帮助过的人!