【问题标题】:How do I handle media metadata in separate class?如何在单独的类中处理媒体元数据?
【发布时间】:2018-11-01 07:18:06
【问题描述】:

我正在使用 JavaFX 媒体类制作媒体播放器。我创建了一个 SongModel 类,它封装了文件中的所有元数据并创建了 Media 和 MediaPlayer 实例。

看起来像这样:

private final StringProperty album =
            new SimpleStringProperty(this, "album");

public String getAlbum(){ return album.get(); }
public void setAlbum(String value){ album.set(value); }
public StringProperty albumProperty() { return album; }

还有看起来像这样的艺术家、年份、标题和专辑封面字段。此外,MediaPlayer 属性公开为只读:

public MediaPlayer getMediaPlayer(){ return mediaPlayer.get(); }
    public ReadOnlyObjectProperty<MediaPlayer> mediaPlayerProperty(){
        return mediaPlayer.getReadOnlyProperty();
    }

我使用 MapChangelistener 来检查该字段是否可用,然后将其传递给 handleMetadata 方法:

private void initializeMedia(String url){

        try {
            final Media media = new Media(url);
            media.getMetadata().addListener(new MapChangeListener<String, Object>(){
                @Override
                public void onChanged(MapChangeListener.Change<? extends String, ? extends Object> ch) {
                    if(ch.wasAdded()){
                        handleMetadata(ch.getKey(), ch.getValueAdded());
                    }
                }                
            });

            mediaPlayer.setValue(new MediaPlayer(media));
            mediaPlayer.get().setOnError(new Runnable() {
                @Override
                public void run() {
                    String errorMessage = mediaPlayer.get().getError().getMessage();
                    System.out.println("MediaPlayer error: "+errorMessage);
                }
            });

        }catch(RuntimeException e){
            System.out.println("Construction error: "+e);
        }
    }

    private void handleMetadata(String key, Object value){
        if(key.equals("album")){
            setAlbum(value.toString());
        } else if (key.equals("artist")){
            setArtist(value.toString());
        } if (key.equals("title")){
            setTitle(value.toString());
        } if (key.equals("year")){
            setYear(value.toString());
        } if (key.equals("image")){
            setAlbumCover((Image)value);
        }
    }

然后我创建了一个提供对 SongModel 的访问的 AbstractView 类:

public abstract class AbstractView {
    protected final SongModel songModel;
    protected final Node viewNode;

    public AbstractView(SongModel songModel){
        this.songModel = songModel;
        this.viewNode = initView();
        }

        public Node getViewNode() {
            return viewNode;
        }

        protected abstract Node initView();
}

但是当我尝试创建一个 MetadataView 类时,我遇到了一些问题。 下面是它的外观:

public class MetadataView extends AbstractView{
    public Label artist;
    public Label album;
    public Label title;
    public Label year;
    public ImageView albumCover;

    public MetadataView(SongModel songModel) {
        super(songModel);
    }

    @Override
    protected Node initView() {
        artist = new Label();
        artist.setId("artist");
        album = new Label();
        album.setId("album");
        title = new Label();
        title.setId("title");
        year = new Label();
        year.setId("year");

        final Reflection reflection = new Reflection();
        reflection.setFraction(0.2);

        final URL url = getClass().getResource("resources/defaultAlbum.png");
        Image image = new Image(url.toString());

        albumCover = new ImageView(image);
        albumCover.setFitWidth(240);
        albumCover.setPreserveRatio(true);
        albumCover.setSmooth(true);
        albumCover.setEffect(reflection);

        final GridPane gp = new GridPane();
        gp.setPadding(new Insets(10));
        gp.setHgap(20);
        gp.add(albumCover, 0,0,1, GridPane.REMAINING);
        gp.add(title, 1,0);
        gp.add(artist, 1,1);
        gp.add(album, 1,2);
        gp.add(year, 1,3);

        final ColumnConstraints c0 = new ColumnConstraints();
        final ColumnConstraints c1 = new ColumnConstraints();

        c1.setHgrow(Priority.ALWAYS);
        gp.getColumnConstraints().addAll(c0,c1);

        final RowConstraints r0 = new RowConstraints();
        r0.setValignment(VPos.TOP);
        gp.getRowConstraints().addAll(r0,r0,r0,r0);


        return gp;

    }

}

下面是我在 start 方法中的调用方式:

metaDataView = new MetadataView(songModel);

问题在于它只显示默认元数据,而不从歌曲模型类中获取它。我尝试在一个类中运行元数据视图代码和数据处理,一切正常,但是当我尝试将它们放在单独的类中时 - 它没有。音乐运行得很好,只是没有显示数据。谁能告诉我我错过了什么?如何让它显示 SongModel 类的元数据?我在这上面花了很多时间,不想浪费掉。

【问题讨论】:

    标签: javafx media


    【解决方案1】:

    经过一天的搜索,我找到了答案:绑定。我所要做的就是将 SongModel 类的 label 属性绑定到 MetadataView 类的 label 属性:

    title.textProperty().bind(songModel.titleProperty());
    artist.textProperty().bind(songModel.artistProperty());
    album.textProperty().bind(songModel.albumProperty());
    year.textProperty().bind(songModel.yearProperty());
    albumCover.imageProperty().bind(songModel.albumCoverProperty());
    

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 1970-01-01
      • 2020-08-26
      • 2013-08-27
      • 1970-01-01
      • 2013-07-03
      • 2013-02-22
      • 2014-05-11
      • 2014-07-01
      相关资源
      最近更新 更多