簡體   English   中英

如何設置 MediaView 的大小,以便所有視頻都適合場景並能與場景成比例增長?

[英]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()創建自定義布局窗格。

要向不可調整大小的節點(例如ImageViewMediaView )添加可調整大小,請將它們包裝在一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM