最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - ImageView Nodes seem to appear at the wrong y position - Stack Overflow

programmeradmin2浏览0评论

I have some strange problem with positioning ImageViews in a Scene in JavaFX.

I want three images of the same size (200 x 200) to appear next to each other at the same height. So I specify the same value in setTranslateY() for each picture. But for some reason, they appear on different heights: Everey next picture appears lower by 200 pixels than the previous one.

Here is the code:

public class Main extends Application {

    @Override
    public void start(Stage myStage) throws IOException {
        myStage.setTitle("title");
        myStage.setScene(getScene());
        stage = myStage;
        myStage.show();
    }

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

    private Scene getScene() {
        List<Node> nodes = new ArrayList<>();
        Image i1 = loadFromPath("... some path");
        Image i2 = loadFromPath("... some other path");
        Image i3 = loadFromPath("... again some other path");
        ImageView v1 = new ImageView(i1);
        ImageView v2 = new ImageView(i2);
        ImageView v3 = new ImageView(i3);
        v1.setTranslateX(100);
        v1.setTranslateY(100);
        v2.setTranslateX(320);
        v2.setTranslateY(100);
        v3.setTranslateX(540);
        v3.setTranslateY(100);
        nodes.add(v1);
        nodes.add(v2);
        nodes.add(v3);
        VBox box = new VBox(nodes.toArray(new Node[0]));
        box.setMinWidth(800);
        box.setMaxWidth(800);
        box.setMinHeight(400);
        box.setMaxHeight(400);

        return new Scene(box);
    }

    private Image loadFromPath(String path) {
        FileInputStream input = null;
        try {
            input = new FileInputStream(path);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        return new Image(input);
    }
}

The result looks like this:

When I use setLayoutX() and setLayoutY() instead of setTranslateX() and setTranslateY(), the result is even worse:

Can someone please explain this result?

I have some strange problem with positioning ImageViews in a Scene in JavaFX.

I want three images of the same size (200 x 200) to appear next to each other at the same height. So I specify the same value in setTranslateY() for each picture. But for some reason, they appear on different heights: Everey next picture appears lower by 200 pixels than the previous one.

Here is the code:

public class Main extends Application {

    @Override
    public void start(Stage myStage) throws IOException {
        myStage.setTitle("title");
        myStage.setScene(getScene());
        stage = myStage;
        myStage.show();
    }

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

    private Scene getScene() {
        List<Node> nodes = new ArrayList<>();
        Image i1 = loadFromPath("... some path");
        Image i2 = loadFromPath("... some other path");
        Image i3 = loadFromPath("... again some other path");
        ImageView v1 = new ImageView(i1);
        ImageView v2 = new ImageView(i2);
        ImageView v3 = new ImageView(i3);
        v1.setTranslateX(100);
        v1.setTranslateY(100);
        v2.setTranslateX(320);
        v2.setTranslateY(100);
        v3.setTranslateX(540);
        v3.setTranslateY(100);
        nodes.add(v1);
        nodes.add(v2);
        nodes.add(v3);
        VBox box = new VBox(nodes.toArray(new Node[0]));
        box.setMinWidth(800);
        box.setMaxWidth(800);
        box.setMinHeight(400);
        box.setMaxHeight(400);

        return new Scene(box);
    }

    private Image loadFromPath(String path) {
        FileInputStream input = null;
        try {
            input = new FileInputStream(path);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        return new Image(input);
    }
}

The result looks like this:

When I use setLayoutX() and setLayoutY() instead of setTranslateX() and setTranslateY(), the result is even worse:

Can someone please explain this result?

Share Improve this question edited Mar 28 at 11:56 desertnaut 60.5k32 gold badges155 silver badges181 bronze badges asked Mar 28 at 11:52 user16038501user16038501 1316 bronze badges 2
  • 3 If you want your nodes to appear in a single row, why not use a layout designed for that, like HBox or TilePane? – VGR Commented Mar 28 at 13:37
  • "images of the same size (200 x 200)" -> Images have sizing constructors if you need them. – jewelsea Commented Mar 28 at 17:38
Add a comment  | 

1 Answer 1

Reset to default 4

Layout panes, such as VBox, lay the components out for you according to an algorithm that is specific to the particular layout pane you are using. They do this by setting the layoutX and layoutY properties of the child nodes.

In particular, a VBox ("vertical box") will lay out the child nodes in a vertical column: see the documentation.

So if you use a layout pane, setting the layoutX and layoutY of the child nodes will have no effect, as they will subsequently be changed by the layout pane when it performs its layout. This explains the result you get in the second screen shot: the images are in the position determined by the layout algorithm of the VBox. The first image is in the top left of the box, and the second image is directly below it. If you remove all calls to setLayoutX(...) and setLayoutY(...), as well as calls to setTranslateX(...) and setTranslateY(...) you will see exactly the same results. The positions shown in the second screenshot are effectively the default positions for the layout defined by a VBox.

Transformations, such as translations managed by setting the translateX and translateY properties, are applied after the layout pane performs its layout. So in the first screen shot, the first image is 100 pixels to the right, and 100 pixels below, the position the VBox placed it (the top left). The second image is 320 pixels to the right and 100 pixels below the position the VBox placed it (the position it appears in the second image). In other words, the translations are relative to the positions defined by the layout in the VBox.

It appears from the coordinates you are setting that you want the images placed horizontally next to each other; to achieve this, just use a HBox instead of a VBox (as suggested in a comment).

public class Main extends Application {

    @Override
    public void start(Stage myStage) throws IOException {
        myStage.setTitle("title");
        myStage.setScene(getScene());
        stage = myStage;
        myStage.show();
    }

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

    private Scene getScene() {
        List<Node> nodes = new ArrayList<>();
        Image i1 = loadFromPath("... some path");
        Image i2 = loadFromPath("... some other path");
        Image i3 = loadFromPath("... again some other path");
        ImageView v1 = new ImageView(i1);
        ImageView v2 = new ImageView(i2);
        ImageView v3 = new ImageView(i3);
        //v1.setTranslateX(100);
        //v1.setTranslateY(100);
        //v2.setTranslateX(320);
        //v2.setTranslateY(100);
        //v3.setTranslateX(540);
        //v3.setTranslateY(100);
        nodes.add(v1);
        nodes.add(v2);
        nodes.add(v3);
        HBox box = new HBox(nodes.toArray(new Node[0]));
        box.setMinWidth(800);
        box.setMaxWidth(800);
        box.setMinHeight(400);
        box.setMaxHeight(400);

        return new Scene(box);
    }

    private Image loadFromPath(String path) {
        FileInputStream input = null;
        try {
            input = new FileInputStream(path);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        return new Image(input);
    }
}

You can use padding to put additional space around the content of the box, if needed:

box.setPadding(new Insets(100, 0, 0, 100)); // top, right, bottom, left

and spacing to put a gap between each image:

box.setSpacing(20);

If you really want to place everything manually (which is very strongly not recommended), use a container that performs no layout (for example, a Pane) instead of the VBox, and set the layoutX and, layoutY properties by hand.

See the documentation and tutorial for more information.

发布评论

评论列表(0)

  1. 暂无评论