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

标签 java multithreading javafx

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

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

问题:
如果我单击包含 mp4(或 mp3)文件的行,则 mp4(或 mp3)文件可以正常播放并显示在我的 anchor Pane 上。当 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++;

最佳答案

如果我理解正确,您正在尝试在播放 .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 方法的相同调用也是如此。

关于JavaFX mp3音频、mp4音频、文本数据叠加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45162770/

相关文章:

java - 同步问题 SharedPreferences?

java - 在场景渲染之前在 Initialize 中调用查找

java - 有没有办法在声明的同时使用内部类呢?

java - 在 NetBeans 中导出变量的运行时值

java - 制作 Swing Logo 测验

java - Hibernate JPA 使用 InheritanceType.JOINED 为每个类创建一个表

java - 如何测试/"Drive"HttpRequest.java(Web 服务器)?

Java 使用 Thread.sleep() 或继续询问

java - JavaFX 中是否有 CHANGEABLE ListProperty?

java - JavaFX 中的一个 ListView 中的 2 个不同列表除以 header