Search code examples
javajavafxjavafx-2javafx-webengine

WebView - Adding a label to display status


I am using the following code with java 8 using javaFx.

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

@SuppressWarnings("all")
public class Highlighter extends Application {

    private boolean marked;


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

    @Override
    public void start(Stage primaryStage) {
        final WebView webView = new WebView();
        final WebEngine engine = webView.getEngine();
        engine.load("http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html");

        final TextField searchField = new TextField("light");
        searchField.setPromptText("Enter the text you would like to highlight and press ENTER to highlight");
        searchField.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                if (engine.getDocument() != null) {
                    highlight(
                            engine,
                            searchField.getText()
                    );
                }
            }
        });

        final Button highlightButton = new Button("Highlight");
        highlightButton.setDefaultButton(true);
        highlightButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                searchField.fireEvent(new ActionEvent());
            }
        });
        final Button markedButton = new Button("Mark it");
        markedButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent actionEvent) {
               marked = true;
            }
        });
        markedButton.setCancelButton(true);

        HBox controls = new HBox(10);
        controls.getChildren().setAll(
                highlightButton,
                markedButton
        );

        VBox layout = new VBox(10);
        layout.getChildren().setAll(searchField, controls, webView);
        searchField.setMinHeight(Control.USE_PREF_SIZE);
        controls.setMinHeight(Control.USE_PREF_SIZE);

        controls.disableProperty().bind(webView.getEngine().getLoadWorker().runningProperty());
        searchField.disableProperty().bind(webView.getEngine().getLoadWorker().runningProperty());

        primaryStage.setScene(new Scene(layout));
        primaryStage.show();

        webView.requestFocus();
    }

    private void highlight(WebEngine engine, String text) {
        engine.executeScript("$('body').removeHighlight().highlight('" + text + "')");
    }

}

My problem is I want to add a label which displays the marked status of a page.

I tried simply adding a Label label = new Label("Marked: " + marked) to the controls, but this does not work.

Any recommendations how I could add a label to my code to display the marked status?

I appreciate your replies!


Solution

  • If you add a Label to controls with your actual code:

    private boolean marked;
    
    Label label = new Label("Marked: " + marked)
    controls.getChildren().setAll(
                highlightButton,
                markedButton,
                label
    );
    

    it will always show Marked: false, no matter if you change marked afterwards.

    If you want that your control responds to changes, JavaFX has observable properties, as you can read here.

    So you can replace the boolean primitive with this property that wraps the boolean value:

    private final BooleanProperty marked=new SimpleBooleanProperty();
    

    Create the label:

        Label label=new Label("Marked: "+marked.get());
        HBox controls = new HBox(10);
        controls.setAlignment(Pos.CENTER_LEFT);
        controls.getChildren().setAll(
                highlightButton,
                markedButton,
                label
        );
    

    Change the event for markedButton:

        markedButton.setOnAction(new EventHandler<ActionEvent>() {
    
            @Override
            public void handle(ActionEvent actionEvent) {
               marked.set(true);
            }
        });
    

    (this will work just once, since for now you don't have implemented a way to reset marked to false again)

    And finally, add a listener for any change inmarked property:

        marked.addListener(new ChangeListener<Boolean>() {
    
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                label.setText("Marked: "+newValue);
            }
        });
    

    Instead of the listener, you can also use Bindings:

    Label label=new Label();
    label.textProperty().bind(Bindings.concat("Marked: ").concat(marked));