2014-10-24 2 views
3

저는 음악 플레이어를 쓰고 있습니다. 사용자가 마우스 버튼을 놓은 후 값을 설정하기 위해 슬라이더 드래그 핸들러를 코딩하는 방법을 모르겠습니다. 간단한 MouseDragged 메서드를 쓸 때마다 미디어 플레이어가 슬라이더가 움직일 때마다 값을 변경하기 때문에 끌어서 감기는 "되감기"소리가납니다. 슬라이더를 재생하는 동안 미디어 플레이어가 청취자의 값을 변경하여 트랙 지속 시간과 동기화합니다. 이것이 내가 지금까지 얻은 것입니다.JavaFX - 마우스 버튼을 드래그 한 후 Slider 값을 설정하십시오.

ChangeListener<Duration> timeListener = new ChangeListener<Duration>() { 
    @Override 
    public void changed(
      ObservableValue<? extends Duration> observableValue, 
      Duration duration, 
      Duration current) { 
     durSlider 
       .setValue(current 
         .toSeconds()); 
    } 
}; 

durSlider.setOnMouseDragged(new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent mouseEvent) { 

        mediaPlayer.seek(Duration.seconds(durSlider.getValue())); 

        } 

       }); 

답변

8

valueChanging property of the slider은 슬라이더가 변경되는 중임을 나타냅니다. 그것은 관찰 속성입니다, 그래서 값이 변경 멈출 때 당신은 그것을 직접 리스너를 첨부하고 응답 할 수 있습니다 : 사용자가 "트랙"를 클릭하면

durSlider.valueChangingProperty().addListener(new ChangeListener<Boolean>() { 
    @Override 
    public void changed(ObservableValue<? extends Boolean> obs, Boolean wasChanging, Boolean isNowChanging) { 
     if (! isNowChanging) { 
      mediaPlayer.seek(Duration.seconds(durSlider.getValue())); 
     } 
    } 
}); 

이 플레이어의 위치를 ​​변경하지 않습니다 슬라이더에 또는 키보드를 사용하여 이동합니다. 이를 위해 listener를 value 속성으로 등록 할 수 있습니다. 값은 시간 청취자를 통해 변경되기 때문에 여기에서주의해야합니다. 이론적으로, 시간 청취자는 슬라이더의 값을 설정해야합니다. 그러면 플레이어의 현재 시간을 이미 가지고있는 정확한 값으로 설정하려고합니다 (아무런 결과도 발생하지 않습니다). 그러나 반올림 오류로 인해 작은 조정이 많이 발생하여 관찰중인 "고정"현상이 발생할 수 있습니다. 변화가있는 경우이 문제를 해결하려면, 오직 더 작은 약간의 최소 금액보다 미디어 플레이어를 이동 :

private static double MIN_CHANGE = 0.5 ; //seconds 

// ... 

durSlider.valueProperty().addListener(new ChangeListener<Number>() { 
    @Override 
    public void changed(ObservableValue<? extends Number> obs, Number oldValue, Number newValue) { 
     if (! durSlider.isValueChanging()) { 
      double currentTime = mediaPlayer.getCurrentTime().toSeconds(); 
      double sliderTime = newValue.doubleValue(); 
      if (Math.abs(currentTime - sliderTime) > 0.5) { 
       mediaPlayer.seek(newValue.doubleValue()); 
      } 
     } 
    } 
}); 

을 마지막으로, 사용자가 드래그하려고하는 경우 슬라이더를 이동하는 시간 리스너를 원하지 않는다 : 답에 대한

import javafx.application.Application; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Slider; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.media.Media; 
import javafx.scene.media.MediaPlayer; 
import javafx.scene.media.MediaView; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class VideoPlayerTest extends Application { 

    private static final String MEDIA_URL = 
      "http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv"; 

    private static final double MIN_CHANGE = 0.5 ; 

    @Override 
    public void start(Stage primaryStage) { 
     MediaPlayer player = new MediaPlayer(new Media(MEDIA_URL)); 
     MediaView mediaView = new MediaView(player); 

     Slider slider = new Slider(); 
     player.totalDurationProperty().addListener((obs, oldDuration, newDuration) -> slider.setMax(newDuration.toSeconds())); 

     BorderPane root = new BorderPane(mediaView, null, null, slider, null); 

     slider.valueChangingProperty().addListener((obs, wasChanging, isChanging) -> { 
      if (! isChanging) { 
       player.seek(Duration.seconds(slider.getValue())); 
      } 
     }); 

     slider.valueProperty().addListener((obs, oldValue, newValue) -> { 
      if (! slider.isValueChanging()) { 
       double currentTime = player.getCurrentTime().toSeconds(); 
       if (Math.abs(currentTime - newValue.doubleValue()) > MIN_CHANGE) { 
        player.seek(Duration.seconds(newValue.doubleValue())); 
       } 
      } 
     }); 

     player.currentTimeProperty().addListener((obs, oldTime, newTime) -> { 
      if (! slider.isValueChanging()) { 
       slider.setValue(newTime.toSeconds()); 
      } 
     }); 

     Scene scene = new Scene(root, 540, 280); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     player.play(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

감사합니다,하지만 당신은 분명히 내 timeListener 속성을 알 didin't :

ChangeListener<Duration> timeListener = new ChangeListener<Duration>() { @Override public void changed( ObservableValue<? extends Duration> observableValue, Duration duration, Duration current) { if (! durSlider.isValueChanging()) { durSlider.setValue(current.toSeconds()); } } }; 

여기 (간결을위한 람다를 사용하여) 완벽한 예입니다. 솔루션을 켜기 만하면 작동하지만 슬라이더는 트랙 지속 시간과 동기화되지 않습니다. 내가 청취자를 넣을 때, 슬라이더의 가치는 사용자가 클릭 할 때뿐만 아니라 지나가는 순간마다 흐르고 있기 때문에 전체 재생 프로세스가 잘못되었습니다. –

+0

아, 나는 그것이 어쨌든 작동 할 것이라고 생각했습니다. 왜냐하면 그것이 이미있는 동일한 위치를 찾아야하기 때문입니다. 반복적으로 아주 작은 조정을 일으키는 어딘가에 반올림이있는 것 같습니다. 업데이트 된 답변보기 –

+0

감사! 이제 제대로 작동합니다. 막 다른 골목처럼 보였지만 정적 인 두 변수를 사용한 아이디어는 훌륭했습니다 –

관련 문제