JavaFX mp3音频,mp4音频,文本数据叠加

时间:2017-07-18 09:30:28

标签: java multithreading javafx

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

说明
我创建了两个服务, FileSearchService FilePreviewService 。 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)的音频仍在播放。

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

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

enter image description here

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

enter image description here

现在,如果我点击一个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++;

1 个答案:

答案 0 :(得分:1)

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

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

解决方案,有一个实例变量,并为其他类调用一些新方法,即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方法添加相同的调用。