Ryan Hilbert
Ryan Hilbert

Reputation: 1925

JavaFX-8 Canvas within BorderPane

I'm pretty new to this whole JavaFX thing, as you can probably tell. This is an issue I ran into recently while playing around with the Canvas node. I've got a BorderPane as my root node, and I'd like to have a Canvas occupy all available space within the center of it. However, I'm having some trouble implementing that exact behavior. Here's the just of what I've been trying:

public void start(Stage stage){
    BorderPane root=new BorderPane();
    Canvas canvas=new Canvas(250,250);
    //canvas.widthProperty().bind(root.widthProperty());
    //canvas.heightProperty().bind(root.heightProperty());
    GraphicsContext gc=canvas.getGraphicsContext2D();
    new AnimationTimer(){
        @Override
        public void handle(long l){
            double width=canvas.getWidth(),height=canvas.getHeight();
            gc.clearRect(0,0,width,height);
            gc.strokeRect(0,0,width,height);
            gc.strokeLine(0,0,width,height);
            gc.strokeLine(0,height,width,0);
        }
    }.start();
    root.setCenter(canvas);
    root.setBottom(new Button("Placeholder"));
    root.setTop(new Button("Placeholder"));
    stage.setScene(new Scene(root));
    stage.show();
}

Instead of expanding as the Pane does, my Canvas just stays centered within it, retaining its original size. If the two commented lines near the top are re-added, the Canvas grows and shrinks as the Pane does, but without regarding the dimensions of its center (as expected). Is there a way to apply this sort of binding behavior to just the center of the BorderPane, or perhaps another way to do this entirely that I'm unaware of?

Upvotes: 4

Views: 3607

Answers (1)

nZeloT
nZeloT

Reputation: 63

EDIT: Just found a much nicer solution today (19.05.2014):

http://fxexperience.com/2014/05/resizable-grid-using-canvas/

So much easier and shorter than mine -.-


Now my original approach:

I had the same problem as you do.

I found a really ugly workaround you can use, but maybe there is another method doing this...

My Workaround:

class MyCanvas {

    private Canvas cv;
    private StackPane box;

    public MyCanvas(Stage stg) {
        cv = new Canvas(500, 500);
        box = new StackPane();

        box.getChildren().add(cv);

        //When the Stage size changes, the canvas size becomes resetted
        //but the Hbox expandes automatically to fit the with again
        //and so the canvas become resized to fit the HBox
        stg.widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
             resize();
            }
        });

        stg.heightProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
            resize();
            }
        }); 

        box.widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
            adapt();
            }
        });

        box.heightProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
            adapt();
            }
        });

        paint();
    }

    private void paint(){
        //Paint something ....
        GraphicsContext ctx = cv.getGraphicsContext2D();

        double w = cv.getWidth();
        double h = cv.getHeight();

        ctx.clearRect(0, 0, w, h);

        ctx.setFill(Color.BLUE);
        ctx.fillRect(0, 0, w, h);
    }

    //Add this HBox to your content pane
    public StackPane getBox() {
        return box;
    }

    public void resize(){
        cv.setWidth(50);
        cv.setHeight(50);
    }

    private void adapt(){
        cv.setHeight(box.getHeight());
        cv.setWidth(box.getWidth());
        paint();
    }
}

And in your Main:

public class Root extends Application{
    public static void main(String[] args){ launch(args); }

    public void start(Stage stg){
        MyCanvas cv = new MyCanvas(stg);
        BorderPane pane = new BorderPane();
        pane.setCenter(pane.getBox());
        stg.setScene(new Scene(pane));
        stg.show();
    }
}

Hope this helps you solving your problem.

nZeloT

Upvotes: 1

Related Questions