How to scale and set coordinates of MediaView?

2019-05-26 02:21发布

I would like to embedd a video in my JavaFx 2.x scene and also resize it and relocate it to my needs. The problem I'm having is following. If I build a MediaView component and then translate X or Y coordinate, then the whole view is being properly moved like so:

MediaView mv = (...)
mv.setTranslateX(200);
mv.setTranslateY(200);

I could do a similar transformation with scaling property:

MediaView mv = (...)
mv.setScaleX(2);
mv.setScaleY(2);

which will properly scale mv instance two times in dimension.

However, the problem is when I combine those two translations. The mv instance is being scaled but it always ends up in screen coordinates (0,0). This is of course incorrect behavior from my perspective.

I have also tried to wrap my MediaView component within some wrapper node, like Group and perform translations on this element. The behavior is the same.

How can I properly move and scale MediaView component at the same time?

Edit:

Here is my code, although I'm using here ImageView. This is irrelevant, however. After running this code, image will be placed at (0,0) instead of (100,100).

    @Override
    public void start(Stage stage) throws Exception {
        Group root = new Group();

        // Img's dimension is 200x200
        javafx.scene.image.Image img = new javafx.scene.image.Image("/home/bachman/projects/cs-player/src/main/resources/content.png");
        ImageView iv = new ImageView(img);
        root.getChildren().add(iv);

        // Move Image View
        iv.setTranslateX(100);
        iv.setTranslateY(100);

        // Scale Image View
        iv.setScaleX(2.0);
        iv.setScaleY(2.0);

        Scene scene = new Scene(root);
        stage.setWidth(600);
        stage.setHeight(600);
        stage.setScene(scene);
        stage.show();
    }

标签: java javafx-2
1条回答
Animai°情兽
2楼-- · 2019-05-26 02:48

When you use setScaleX, setScaleY, scaling occurs from the center of the node.

If you want to translate by an amount in addition to scaling, you need to take the scaling expansion into account when you set the required translation values. For example, if the node doubles in size (and you want to translate the node to a position relative to the upper left corner of the unscaled node), you need to translate by an additional half the node width and height.

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.media.*;
import javafx.scene.transform.*;
import javafx.stage.Stage;

public class TransformedVideo extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  @Override public void start(final Stage stage) throws Exception {
    final MediaPlayer oracleVid = new MediaPlayer(new Media("http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv"));
    final MediaView mediaView = new MediaView(oracleVid);
    mediaView.setFitWidth(320); mediaView.setFitHeight(240); mediaView.setPreserveRatio(false);

    mediaView.setTranslateX(mediaView.getFitWidth()  / 2 + 200); 
    mediaView.setTranslateY(mediaView.getFitHeight() / 2 + 200);
    mediaView.setScaleX(2); mediaView.setScaleY(2);

// alternative method of scaling and translating.    
//    mediaView.getTransforms().addAll(
//      new Translate(200, 200),
//      new Scale(2, 2)
//    );

    Group group = new Group(mediaView);
    stage.setScene(new Scene(group, 1250, 800));
    stage.show();

    oracleVid.play();

    System.out.println(group.getBoundsInParent());
  }
}

When performing multiple transforms on a node, rather than using the setScale/setTransform/setRotate methods, it is often easier to just supply a list of transforms to the getTransforms() method.

查看更多
登录 后发表回答