[英]How do I set the size of the MediaView so that all videos fit in the scene and can grow proportionally to the scene?
同時,讓視頻完全融入場景。 此代碼試圖在一個場景中放置三個視頻。
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import java.awt.*;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
public class MainListener extends Application {
public static final int NUM_CHANNELS = 3;
public static String current_directory;
Button btnPlay = new Button("Play");
ArrayList<MediaBox> mediaBoxes = new ArrayList<MediaBox>();
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
primaryStage = new Stage();
VBox vBox = new VBox();
FlowPane flowPane = new FlowPane();
flowPane.setOrientation(Orientation.HORIZONTAL);
Scene scene = new Scene(vBox,dimension.getWidth()/2, dimension.getHeight()/2);
getPathToWorkDirectory();
for(int i = 0; i < NUM_CHANNELS; i++){
MediaBox mediaBox = new MediaBox(i+1);
mediaBoxes.add(mediaBox);
flowPane.getChildren().add(mediaBox);
}
setActions();
vBox.getChildren().addAll(btnPlay, flowPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public void setActions() {
btnPlay.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
for (MediaBox mediaBox : mediaBoxes) {
mediaBox.getMediaPlayer().play();
}
}
});
}
public static void getPathToWorkDirectory(){
current_directory = new File("").getAbsolutePath();
System.out.println(current_directory);
}
}
頻道的媒體視圖。 我知道您需要使用 DoubleProperty 按比例調整大小。 但同時不明白如何正確綁定場景大小到VBox節點,然后將所有MediaView元素綁定到VBox
class MediaBox extends MediaView {
private String path;
private Media media;
public MediaBox(Integer num_channel){
//Path to video
path = MainListener.current_directory + "\\ch_" + num_channel.toString() + ".mp4";
media = new Media(pathToURL(path));
DoubleProperty mvw = fitWidthProperty();
DoubleProperty mvh = fitHeightProperty();
mvw.bind(Bindings.selectDouble(sceneProperty(), "width"));
mvh.bind(Bindings.selectDouble(sceneProperty(), "height"));
setMediaPlayer(new MediaPlayer(media));
}
private String pathToURL(String src_path) {
File file = new File(src_path);
String out_path = null;
try {
out_path = file.toURI().toURL().toString();
} catch (MalformedURLException mURL_E) {
System.out.println("Error in path URL for video");
}
return out_path;
}
}
該視頻超出了 window
避免對布局任務使用綁定。 喜歡使用標准布局窗格,如果沒有滿足您的需要(通常不太可能),則通過覆蓋layoutChildren()
創建自定義布局窗格。
要向不可調整大小的節點(例如ImageView
和MediaView
)添加可調整大小,請將它們包裝在一個Region
中並使用該節點的 API 將它們調整為區域的大小。
創建一個包含MediaView
的自定義Region
,並將MediaView
的大小調整為區域的大小:
public class MediaBox extends Region {
private final MediaView mediaView ;
public MediaBox(MediaView mediaView) {
this.mediaView = mediaView ;
getChildren().add(mediaView);
}
@Override
protected void layoutChildren() {
double width = getWidth();
double height = getHeight();
mediaView.setFitWidth(width);
mediaView.setFitHeight(height);
Bounds mvBounds = mediaView.getBoundsInLocal();
mediaView.relocate((width-mvBounds.getWidth())/2, (height-mvBounds.getHeight())/2);
}
}
您可能還需要覆蓋computePrefWidth(...)
、 computePrefHeight(...)
方法,以獲得所需的行為。
現在您可以將MediaView
包裝在這個MediaBox
中並使用任何正常的布局策略:
public void start(Stage primaryStage) {
VBox vBox = new VBox();
Screen screen = Screen.getPrimary();
Rectangle2D dimension = screen.getBounds();
FlowPane flowPane = new FlowPane();
flowPane.setOrientation(Orientation.HORIZONTAL);
Scene scene = new Scene(vBox, dimension.getWidth()/2, dimension.getHeight()/2);
for(int i = 0; i < NUM_CHANNELS; i++){
String url = Paths.get(
System.getProperty("user.dir"),
"ch_"+i+".mp4"
).toURI().toString();
MediaView mediaView = new MediaView(
new MediaPlayer(
new Media(url)
)
);
mediaView.setPreserveRatio(true);
MediaBox mediaBox = new MediaBox(mediaView);
mediaBoxes.add(mediaBox);
flowPane.getChildren().add(mediaBox);
}
setActions();
vBox.getChildren().addAll(btnPlay, flowPane);
primaryStage.setScene(scene);
primaryStage.show();
}
我重寫了你留下的代碼。 但是我仍然遇到根據場景更改Region
大小的問題。 我添加了 scene.widthProperty.addListener( scene.widthProperty.addListener()
和scene.heigthProperty.addListener()
來解決這個問題並且它有效。 但這種做法正確嗎?
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Orientation;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Screen;
import javafx.stage.Stage;
import java.nio.file.Paths;
import java.util.ArrayList;
public class MainListener extends Application {
public static final int NUM_CHANNELS = 6;
Button btnPlay = new Button("Play");
ArrayList<MediaBox> mediaBoxes = new ArrayList<MediaBox>();
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
VBox vBox = new VBox();
Screen screen = Screen.getPrimary();
Rectangle2D dimension = screen.getBounds();
FlowPane flowPane = new FlowPane();
flowPane.setOrientation(Orientation.HORIZONTAL);
Scene scene = new Scene(vBox, dimension.getWidth(), dimension.getHeight());
for(int i = 0; i < NUM_CHANNELS; i++){
String url = Paths.get(System.getProperty("user.dir"),"ch_" + (i+1) + ".mp4").toUri().toString();
System.out.println(url);
MediaView mediaView = new MediaView(
new MediaPlayer(
new Media(url)
)
);
mediaView.setPreserveRatio(true);
MediaBox mediaBox = new MediaBox(mediaView);
scene.heightProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1) {
mediaBox.setPrefHeight(number.doubleValue()/4);
System.out.println("Height: " + number);
}
});
scene.widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1) {
mediaBox.setPrefWidth(number.doubleValue()/4);
System.out.println("Width: " + number);
}
});
mediaBoxes.add(mediaBox);
flowPane.getChildren().add(mediaBox);
}
setActions();
vBox.getChildren().addAll(btnPlay, flowPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public void setActions() {
btnPlay.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
for(MediaBox mediaBox : mediaBoxes){
mediaBox.getMediaView().getMediaPlayer().play();
}
}
});
}
}
這里我只設置了setMinSize(300,400)
並添加了getMediaView()
class MediaBox extends Region{
private final MediaView mediaView;
public MediaBox(MediaView mediaView){
this.mediaView = mediaView;
layoutChildren();
getChildren().add(mediaView);
}
@Override
protected void layoutChildren(){
setMinSize(300, 400);
double width = getWidth();
double height = getHeight();
mediaView.setFitHeight(height);
mediaView.setFitWidth(width);
Bounds mvBounds = mediaView.getBoundsInLocal();
mediaView.relocate((width-mvBounds.getWidth()/2), (height-mvBounds.getHeight())/2);
}
public MediaView getMediaView(){
return mediaView;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.