Question

I want to create a refresh button for my webView that will be on top of the view (even if it hides part of the view), when I place the button on the Grid Pane it pushes the webView down or to the side (depends where I place the button)

How can I place my "refresh" button on top of the webView and not move it aside?

import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class webviewbrowser extends Application {

@Override public void start(Stage primaryStage) throws Exception {
    Pane root = new WebViewPane();
    primaryStage.setScene(new Scene(root, 1024, 768));
    primaryStage.setFullScreen(true);
    primaryStage.show();
}
public static void main(String[] args) {
    launch(args);
}

/**
 * Create a resizable WebView pane
 */
public class WebViewPane extends Pane {

    public WebViewPane() {
        VBox.setVgrow(this, Priority.ALWAYS);
        setMaxWidth(Double.MAX_VALUE);
        setMaxHeight(Double.MAX_VALUE);

        WebView view = new WebView();
        view.setMinSize(500, 400);
        view.setPrefSize(500, 400);
        final WebEngine eng = view.getEngine();
        eng.load("http://google.com");
        //final TextField locationField = new TextField("http://www.google.com");
        //locationField.setMaxHeight(Double.MAX_VALUE);
        Button goButton = new Button("Refresh");
        goButton.setDefaultButton(true);

        EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent event) {
                eng.reload();
            }
        };
        goButton.setOnAction(goAction);

        GridPane grid = new GridPane();
        grid.setVgap(0);
        grid.setHgap(0);

        GridPane.setConstraints(goButton,2,0,2,1, HPos.RIGHT, VPos.BOTTOM, Priority.ALWAYS, Priority.ALWAYS);
        GridPane.setConstraints(view, 0, 0, 2, 1, HPos.CENTER, VPos.CENTER, Priority.SOMETIMES, Priority.SOMETIMES);
        grid.getColumnConstraints().addAll(
                new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true),
                new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true)
        );
        grid.getChildren().addAll(goButton, view);
        getChildren().add(grid);
    }

    @Override protected void layoutChildren() {
        List<Node> managed = getManagedChildren();
        double width = getWidth();
        double height = getHeight();
        double top = getInsets().getTop();
        double right = getInsets().getRight();
        double left = getInsets().getLeft();
        double bottom = getInsets().getBottom();
        for (int i = 0; i < managed.size(); i++) {
            Node child = managed.get(i);
            layoutInArea(child, left, top,
                           width - left - right, height - top - bottom,
                           0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
        }
    }
}

}

Was it helpful?

Solution

If you want to stack one component on top of another, don't use a GridPane for layout, instead use a parent that allows layout components to be placed on top of one another. For example, a standard Pane, a StackPane, Group or Region. In these stacked style layouts, the components are rendered in order of the child component's position in the parent's child list.

In your sample code you are already extending Pane, so get rid of all of the grid code and just do:

getChildren().addAll(view, goButton);

instead of:

grid.getChildren().addAll(goButton, view);

Modify the layout properties of your goButton to position it within a parent which does not manage the layout position of it's children, e.g. you can call goButton.relocate(xPos, yPos).

You have some custom stuff in the layoutChildren method you override that may mess up the default Pane layout processing logic. Overriding layoutChildren is more of an advanced layout topic and I wouldn't advise it for beginners.

googleoverlaid

Here is an updated sample you could look at which uses some of the concepts mentioned in this answer.

import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.web.*;
import javafx.stage.Stage;

public class WebViewBrowser extends Application {
    @Override public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(new WebViewPane("http://google.com")));
        stage.setFullScreen(true);
        stage.show();
    }

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

class WebViewPane extends Pane {
    final WebView view     = new WebView();
    final Button  goButton = createGoButton(view.getEngine());

    public WebViewPane(String initURL) {
        view.getEngine().load(initURL);

        getChildren().addAll(
            view, 
            goButton
        );

        initLayout();
    }

    private Button createGoButton(final WebEngine eng) {
        Button go = new Button("Refresh");
        go.setDefaultButton(true);
        go.setOnAction(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent event) {
                eng.reload();
            }
        });

        return go;
    }

    private void initLayout() {
        setMinSize(500, 400);
        setPrefSize(1024, 768);

        view.prefWidthProperty().bind(widthProperty());
        view.prefHeightProperty().bind(heightProperty());

        goButton.setLayoutX(10);
        goButton.layoutYProperty().bind(
            heightProperty().subtract(20).subtract(goButton.heightProperty())
        );
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top