5

だから私は今これを1週間探していて、すべての問題を読んでいますが、私のものとまったく同じ問題を尋ねているようには見えませんでした(私が望むものと同様の他のソリューションをリバースエンジニアリングしてみてください。

穴居人のスタイルを説明しました: メタデータを使用してリストを作成しようとしています。

  1. マルチ ダイアログで開き、複数の mp3 を選択します
  2. ファイルをArrayList<File>
  3. 強化された for ループでファイルをループし、メディア変数を使用してメタデータを抽出します
  4. メタデータ (「アーティスト」など) の情報は、たとえば ArrayList に保存したいものです

問題は、強化されたループが終了した後でしかリスナーが機能 ArrayList<String>しないことです。

ここにサンプルがあります:

ArrayList<String> al;
String path;
public void open(){
    files=chooser.showOpenMultipleDialog(new Stage());
    for( File f:files){             
        path=f.getPath();
        Media media = new Media("file:/"+path.replace("\\", "/").replace(" ", "%20"));
        al= new ArrayList<String>();
        media.getMetadata().addListener(new MapChangeListener<String, Object>() {                 
            public void onChanged(Change<? extends String, ? extends Object> change) {
                if (change.wasAdded()) {
                    if (change.getKey().equals("artist")) {
                        al.add((String) change.getValueAdded());
                     }
                }
            }
        });
    }//close for loop
    //then i want to see the size of al like this
    system.out.println(al.size());
    //then it returns 1 no matter how much file i selected
    //when i system out "al" i get an empty string
4

3 に答える 3

3

リスナーを追加してメディア ソース メタデータを読み取るもう 1 つの方法は、mediaplayer .setOnReady(); でその情報を抽出することです。これは、Java コントローラー クラスの一部の例です。

public class uiController は Initializable {

@FXML private Label label;
@FXML private ListView<String> lv;
@FXML private AnchorPane root;
@FXML private Button button;

private ObservableList<String> ol= FXCollections.observableArrayList();
private List<File> selectedFiles;
private final Object obj= new Object();

@Override
public void initialize(URL url, ResourceBundle rb) {
    assert button != null : "fx:id=\"button\" was not injected: check your FXML file 'ui.fxml'.";
    assert label != null : "fx:id=\"label\" was not injected: check your FXML file 'ui.fxml'.";
    assert lv != null : "fx:id=\"lv\" was not injected: check your FXML file 'ui.fxml'.";
    assert root != null : "fx:id=\"root\" was not injected: check your FXML file 'ui.fxml'.";

    // initialize your logic here: all @FXML variables will have been injected
    lv.setItems(ol);
}  

@FXML private void open(ActionEvent event) {
    FileChooser.ExtensionFilter extention= new FileChooser.ExtensionFilter("Music Files", "*.mp3","*.m4a","*.aif","*.wav","*.m3u","*.m3u8");
    FileChooser fc= new FileChooser();
    fc.setInitialDirectory(new File(System.getenv("userprofile")));
    fc.setTitle("Select File(s)");
    fc.getExtensionFilters().add(extention);
    selectedFiles =fc.showOpenMultipleDialog(root.getScene().getWindow());
    if(selectedFiles != null &&!selectedFiles.isEmpty()){
        listFiles();
    }
}
/**
 * Convert each fie selected to its URI
 */
private void listFiles(){ 
    try {
        for (File file : selectedFiles) {
            readMetaData(file.toURI().toString());
            synchronized(obj){
               obj.wait(100);
            }
        }
    } catch (InterruptedException ex) {
    }
    System.gc();
}
/**
 * Read a Media source metadata 
 * Note: Sometimes the was unable to extract the metadata especially when 
 * i have selected large number of files reasons i don't known why
 * @param mediaURI Media file URI
 */
private void readMetaData(String mediaURI){
    final MediaPlayer mp= new MediaPlayer(new Media(mediaURI));
    mp.setOnReady(new Runnable() {

        @Override
        public void run() {
            String artistName=(String) mp.getMedia().getMetadata().get("artist");
            ol.add(artistName);
            synchronized(obj){//this is required since mp.setOnReady creates a new thread and our loopp  in the main thread
                obj.notify();// the loop has to wait unitl we are able to get the media metadata thats why use .wait() and .notify() to synce the two threads(main thread and MediaPlayer thread)
            }
        }
    });
}

}

行われたいくつかの変更は、ObservableList を使用して、メタデータからアーティスト名を保存します

コードでこれを見つけるでしょう

同期(オブジェクト){
                    obj.wait(100);
                }
これを行うのは、mediaplayer .setOnReady() が新しいスレッドを作成し、ループがメイン アプリケーション スレッドにあるためです。ループは、他のスレッドが作成されるまでしばらく待機する必要があり、メタデータを抽出できるようになります。 .setOnReady() があります
同期(オブジェクト){
                    obj.notify;
                }
メインスレッドをウェイクアップするため、ループは次のアイテムに移動できます

これが最善の解決策ではないことは認めますが、ファイルのリストから JavaFx メディア メタデータを読み取るためのより良い方法を知っている人なら誰でも歓迎します。完全な Netbeans プロジェクトはこちらhttps://docs.google .com/file/d/0BxDEmOcXqnCLSTFHbTVFcGIzT1E/edit?usp=共有

さらに、メタデータの使用を悪用する JavaFX を使用して小さな MediaPlayer アプリケーションを作成しましたhttps://docs.google.com/file/d/0BxDEmOcXqnCLR1Z0VGN4ZlJkbUU/edit?usp=sharing

于 2013-02-25T11:18:16.540 に答える
0

次の関数を使用して、特定の Media オブジェクトのメタデータを取得できます。

public static void initializeMetaData(Media media) {
    final Ref<Boolean> ready = new Ref<>(false);

    MediaPlayer mediaPlayer = new MediaPlayer(media);
    mediaPlayer.setOnReady(() -> {
        synchronized (ready) {
            ready.set(false);
            ready.notify();
        }
    });

    synchronized (ready) {
        if (!ready.get()) {
            try {
                ready.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

ただし、JavaFX スレッドから呼び出さないでください。そうしないとinitializeMetaData、スレッドがデッドロックに陥ります。

PS: そのような回避策を構築しなければならないというのは、本当にばかげています。将来、メディアがこの仕事をする initialize() メソッドを提供することを願っています。

于 2015-03-06T16:27:52.577 に答える