【问题标题】:JavaFX mp3 audio, mp4 audio, text Data superimposingJavaFX mp3音频、mp4音频、文本数据叠加
【发布时间】:2017-07-18 09:30:27
【问题描述】:

我正在开发一个应用程序,它可以在不同文件夹位置查找文件并在表格视图中显示所有文件。如果用户单击一行,则该文件将显示在程序的右侧。目前,它适用于 txt、mp3 文件和 mp4 文件。

说明:
我创建了两个服务,FileSearchServiceFilePreviewService。 FileSearchService 搜索文件并将其添加到静态 observableList 中。 FilePreviewService 获取所选行,检查文件是否为 txt 或 mp3 或其他类型,并使用 FileProcessor 抽象类来处理所选项目。如果选择的项目是 txt 类型,则 FileProcessor 的子类 TextProcessor 将发挥作用并返回一个 AnchorPane,其中 TextArea 作为附加到该 AnchorPane 的子项。 textarea 设置从所选项目(行)获得的文本。最后将anchorPane 返回给主控制器。然后主控制器显示该项目。

问题:
如果我单击包含 mp4(或 mp3)文件的行,则 mp4(或 mp3)文件可以正常播放并显示在我的 anchorPane 上。在播放 mp4(或 mp3)时,如果我单击 txt 文件,则该文件的数据会显示在 anchorPane 上,但 mp4(或 mp3)的音频仍在播放。

以下是描述我的问题的两张图片。

我点击了一个视频文件,视频显示在我的应用程序的右侧。

现在我点击一个 txt 文件,然后 anchorPane 显示 textData 但视频(而不是音频)仍在播放。

现在,如果我单击 mp3 文件,则 mp3 和 mp4 音频会叠加。

我想要什么

我只想执行一项。如果正在播放 mp3 文件并且如果我单击 mp4 视频,则 mp3 应该停止并且视频应该播放。我的应用程序可以处理多个连续的 mp3 或 mp4 或 txt 点击。单击 mp4 文件,然后单击 txt 文件不会得到处理。

FilePreviewService.Java

public class FilePreviewService extends Service<Void> {
    FileModel model;
    private FileProcesser fileProcesser;
    String fileExtension = "";


    public FileProcesser getFileProcesser() {
        return fileProcesser;
    }

    public FilePreviewService(FileModel model) {
        this.model = model;
        this.fileExtension = reverseFileName(getFileExtension(model));

    }

    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                System.out.println("FIlePreviewService, createTask() Thread = " + Thread.currentThread().getName());
               fileProcesser = FileUtility.getFileProcesserFromUtil(fileExtension);
               getFileProcesser().processFile(model.getFileLocation());
                return null;
            }


        };
    }
}

AudioProcesser.Java

public final class AudioProcesser extends FileProcesser{
    static AudioProcesser audioProcesser;
     Media media;
     MediaPlayer mediaPlayer;


    public static AudioProcesser getAudioProcesser() {
        if (audioProcesser == null)
            audioProcesser = new AudioProcesser();
        return audioProcesser;
    }

    @Override
    public void processFile(String fileLocation) throws Exception {
        switch (getAudioMediaStatus()) {
            case NOT_PLAYED:
                playMedia(fileLocation);
                break;
            case PLAYING:
                /* TIP:
                If mediaPlayer.stop is placed after the line
                *  media = new Media(new File(fileLocation).toURI().toString());
                    mediaPlayer = new MediaPlayer(media);
                    then multiple music play together when multiple different row gets selected,
                    one after another
                */
                mediaPlayer.stop();
                playMedia(fileLocation);
                break;
            default:
                System.out.println("Audio in default case");
        }
    }

    private void playMedia(String fileLocation) {
        media = new Media(new File(fileLocation).toURI().toString());
        mediaPlayer = new MediaPlayer(media);
        mediaPlayer.play();
        setAudioMediaStatus(PLAYING);
    }
}

VideoProcesser.Java

public class VideoProcesser extends FileProcesser {
    static VideoProcesser videoProcesser = null;
    MediaPlayer mediaPlayer;
    Media media;
    MediaView mediaView;

    @Override
    public void processFile(String fileLocation) throws Exception {
        switch (getVideoMediaStatus()) {
            case NOT_PLAYED:
                playVideo(fileLocation);
                break;
            case PLAYING:
                mediaPlayer.stop();
                playVideo(fileLocation);
                break;
            default:
                System.out.println("Audio in default case");
        }


//        pane.getChildren().add();
    }

    @Override
    public AnchorPane getPane(){
        return pane;
    }


    private void playVideo(String fileLocation) {
        System.out.println("VideoProcesser Thread = " + Thread.currentThread().getName());
        media = new Media(new File(fileLocation).toURI().toString());
        mediaPlayer = new MediaPlayer(media);
//        mediaPlayer.setAutoPlay(true);
        if(mediaView == null) {
            mediaView = new MediaView(mediaPlayer);
        }
        mediaView.setMediaPlayer(mediaPlayer);
        mediaView.setPreserveRatio(true);
        mediaPlayer.play();
        mediaPlayer.setOnError(() -> System.out.println("Current error: "+mediaPlayer.getError()));
        setVideoMediaStatus(PLAYING);
        pane.getChildren().add(mediaView);
    }

    public static FileProcesser getVideoProcesser() {
        if(videoProcesser == null)
            videoProcesser = new VideoProcesser();
        return videoProcesser;
    }
}

TextProcesser.Java

public class TextProcesser extends FileProcesser {

    static TextProcesser textProcesser = null;

    public static FileProcesser getTextProcesser() {
        if(textProcesser == null)
            textProcesser = new TextProcesser();
        return textProcesser;
    }

    @Override
    public void processFile(String fileLocation) throws IOException {
        InputStream inputStream = new FileInputStream(fileLocation);
        Scanner sc = null;

        //text file: 25.1_-_Marvel_Graph.txt, size 1.5MB
        System.out.println("Data reading started = " + new Date());
        if (inputStream != null) {
            StringBuilder txtData = new StringBuilder("");
            try {
                sc = new Scanner(inputStream, "UTF-8");
                while (sc.hasNextLine()) {
                    txtData.append(sc.nextLine());
                }
                // note that Scanner suppresses exceptions
                if (sc.ioException() != null) {
                    throw sc.ioException();
                }
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (sc != null) {
                    sc.close();
                }
            }
            dataToDisplay = txtData.toString();
        }
        System.out.println("Data reading finished = " + new Date());

    }

    @Override
    public AnchorPane getPane(){
        TextArea txtArea = new TextArea();
        txtArea.setEditable(false);
        txtArea.setText((String) dataToDisplay);
        txtArea.setPrefHeight(778);
        txtArea.setWrapText(true);
        pane.getChildren().add(txtArea);
        return pane;
    }
}

MainController.Java

public void initialize(URL location, ResourceBundle resources) {
        init();
        initFilePreviewExecutors();

        for (int i = 0; i < locationsToSearch.length; i++) {
            fileModel = new FileModel(locationsToSearch[i]);
            FileSearchService fileSearchService = new FileSearchService(fileModel);
            fileSearchService.setExecutor(fileSearchExecutor);
            fileSearchService.setOnSucceeded(e -> {
                fileSearchService.setFileSearchCompleted(true);
                searchFinished = true;
            });
            fileSearchService.start();

            CacheFileService cfs = new CacheFileService(locationsToSearch[i]);

        }
        try {
            stop();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        nameCol.setCellValueFactory(new PropertyValueFactory<>("fileName"));
        sizeCol.setCellValueFactory(new PropertyValueFactory<>("fileSize"));
        locationCol.setCellValueFactory(new PropertyValueFactory<>("fileLocation"));

        recordsTableView.setItems(fileModel.getData());

        recordsTableView.setContextMenu(new ContextMenu(showRecordInfo));

        recordsTableView.setRowFactory(tv -> {
            TableRow<FileModel> row = new TableRow<>();
            row.setOnMouseClicked(event -> {
                if(!row.isEmpty() && event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 1) {
                    FileModel fileModel = row.getItem();
                    filePreviewService = new FilePreviewService(fileModel);
                    filePreviewService.setExecutor(filePreviewExecutor);
                    filePreviewService.setOnSucceeded(event1 -> {
                        recordPreviewPane = filePreviewService.getFileProcesser().getPane();
                        if(recordPreviewPane == null) {
                            System.out.println("RECORDPREVIEWPANE IS NULL");
                        }
                        previewPane.setContent(recordPreviewPane);
                    });
                    filePreviewService.restart();

                } else if(!row.isEmpty() && event.getButton() == MouseButton.SECONDARY) {
                    FileModel fileModel = row.getItem();
                        showRecordInfo.setOnAction( e -> {
                        Scene scene = defaultViewFactory.getRecordInfoScene(fileModel);
                        Stage stage = new Stage();
                        stage.setScene(scene);
                        stage.show();
                    });

                }
            });
            return row;});


    }

我希望我把我的问题说清楚了。如果您想查看其他 java 文件,那么下面是该项目的链接。 Github :

编辑:我解决问题的方式非常低效。我在 FilePreviewService 中添加了更多代码。当然,下面的代码需要满足更多的条件。这只是一种非常低效的方法。

 getFileProcesser().processFile(model.getFileLocation());
                if(i > 0) {
                    oldFileProcesser = fileProcesserStack.pop();
                }
                if(fileProcesser != null) {
                    fileProcesserStack.push(fileProcesser);
                }

                //audio and video consecutive play fixing

                if(i > 0 && (oldFileProcesser instanceof AudioProcesser || oldFileProcesser instanceof VideoProcesser)
                        && !(fileProcesser instanceof AudioProcesser || fileProcesser instanceof VideoProcesser)) {
                    if(oldFileProcesser instanceof  AudioProcesser) {
                        AudioMediaStatus.setAudioMediaStatus(AudioMediaStatus.JUST_STOP); }
                    if(oldFileProcesser instanceof  VideoProcesser) {
                        VideoMediaStatus.setVideoMediaStatus(VideoMediaStatus.JUST_STOP);}
                    oldFileProcesser.processFile("");
                }
                i++;

【问题讨论】:

    标签: java multithreading javafx


    【解决方案1】:

    如果我理解正确,您是在播放 .mp4 时尝试停止 .mp3,反之亦然。

    首先是您的问题的原因。当您开始播放 .mp3 时,您正在调用 AudioProcesser,很酷,很棒。所以你通过那个类开始一个新的MediaPlayer。 但是,您使用 VideoProcesser 类做同样的事情。所以现在你有两个 MediaPlayers 同时运行,这就是音频覆盖的原因。

    解决方案,有一个实例变量并公开一些新方法供其他类调用,即stopMediaPlayer()方法。

    下面的示例,对您的代码进行尽可能少的更改:

    public final class AudioProcesser extends FileProcesser{
        //Always have one instance of the variable.
        static AudioProcesser audioProcesser = new AudioProcesser();
        private Media media;
        private MediaPlayer mediaPlayer;
    
        public static AudioProcesser getAudioProcesser() {
            return audioProcesser;
        }
    
        //Added an exposure to the underlying audioMediaStatus
        public void setAudioMediaStatus(AudioMediaStatus status){
            AudioMediaStatus.setAudioMediaStatus(status);
        }
        //Another exposure to the underlying audioMediaStatus
        public AudioMediaStatus getAudioMediaStatus(){
            return AudioMediaStatus.getAudioMediaStatus();
        }
        //Used only for this class
        private void setMediaPlayer(String fileLocation){
            Media media = new Media(new File(fileLocation).toURI().toString());
            mediaPlayer = new MediaPlayer(media);
        }
    
        //Exposed a stop method.
        public void stopMedia(){
            if(mediaPlayer != null) {
                //Change this accordingly.
                setAudioMediaStatus(AudioMediaStatus.NOT_PLAYED);
                mediaPlayer.stop();
            }
        }
    
        @Override
        public void processFile(String fileLocation) throws Exception {
            switch (getAudioMediaStatus()) {
                case NOT_PLAYED:
                    playMedia(fileLocation);
                    break;
                case PLAYING:
                    /* TIP:
                    If mediaPlayer.stop is placed after the line
                    *  media = new Media(new File(fileLocation).toURI().toString());
                        mediaPlayer = new MediaPlayer(media);
                        then multiple music play together when multiple different row gets selected,
                        one after another
                    */
                    mediaPlayer.stop();
                    playMedia(fileLocation);
                    break;
                default:
                    System.out.println("Audio in default case");
            }
        }
    
        private void playMedia(String fileLocation) {
    
            VideoProcesser.getVideoProcesser().stopMedia();
            //Moved the previous statements to its own method.
            setMediaPlayer(fileLocation);
            mediaPlayer.play();
            setAudioMediaStatus(AudioMediaStatus.PLAYING);
        }
    }
    

    如您所见,我添加了一些项目,即一些方法,并且我摆脱了您的静态导入。需要注意的重要事项是stopMedia() 方法和playMedia() 方法中的第一行。

    stopMedia 方法完全符合其名称的含义。在playMedia 方法中,可以看到我在第一行添加了VideoProcesser.getVideoProcesser().stopMedia()

    Audio/VideoProcesser 类几乎相同,因此添加的方法和细微调整将转移过来,我已经对此进行了测试,它确实有效。

    由于您还想在选择txt 文件时停止音频/视频,因此您还需要在该类中添加对视频和音频stopMedia 方法的相同调用。

    【讨论】:

    • 是的,我明白这一点。稍后我将为我的 VideoProcesser 添加更多功能,例如录制视频文件的某些部分。即使我将音频和视频处理器合并在一起,另一个问题仍然存在,即在播放音频时,如果我然后单击文本文件,则音频将继续播放。我解决这个问题的方式非常低效,我已经更新了这个问题。我实际上正在使用文件处理器并将其放在堆栈上并检查先前的文件处理器是否属于 AudioProcessor 类型,然后调用它们各自的 processFile() 方法并停止它。
    • 啊,我明白了。好吧,我试图检查您的代码并对其进行重构,但是对于我的想法而言,这需要进行太多更改。也许其他人会有一个想法
    • 你能告诉我你的想法吗?
    • 使用实例变量并公开一些方法来停止媒体播放器。不知道当你启动新线程时它会如何工作。
    • 我睡在上面,我有办法了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 2015-12-05
    相关资源
    最近更新 更多