简体   繁体   中英

Javafx show virtual keyboard

I want never to hide the virtual keyboard like Programmatically show/hide virtual keyboard

OR (if above point is not possible then)

I want to remove/hide/disable below (highlighted green left bottom) button from virtual keyboard.

在此处输入图片说明

I am using Java 8 and Javafx.


Update 1


I have integrated José Pereda's code . The hide button ( .hide ) is hidden successfully. Now I am having hard time to keep displaying the keyboard for all time.

Problem:

Whenever there is focus out from the textarea the keyboard hides. So when user clicks on Convert Now! button the keyboard hides. I tried to stay focused on textarea by using textarea.requestFocus(); , but there is a blinking of keyboard (hide then show).

My Goal

To never hide the keyboard at any case unless the program is not terminated.

Code: You can check my code on github too.

package com.binaryname.view;

import java.util.Iterator;

import com.sun.javafx.print.PrintHelper;
import com.sun.javafx.print.Units;
import com.sun.javafx.scene.control.skin.FXVK;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.print.PageLayout;
import javafx.print.PageOrientation;
import javafx.print.Paper;
import javafx.print.Printer;
import javafx.print.PrinterJob;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Path;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.transform.Scale;
import javafx.stage.PopupWindow;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;

public class Main extends Application {

    private PopupWindow keyboard;

    private final Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
    private final Rectangle2D bounds = Screen.getPrimary().getBounds();
    private final double taskbarHeight = bounds.getHeight() - visualBounds.getHeight();

    @Override
    public void start(Stage primaryStage) throws Exception {

        primaryStage.setTitle("Binary Name");

        Label helloLbl = new Label("Hello");
        helloLbl.setAlignment(Pos.CENTER);
        helloLbl.setFont(Font.font("Comic Sans MS", FontWeight.BOLD, 68));
        helloLbl.setStyle("-fx-background-color: red;padding: 20px;");
        helloLbl.setTextFill(Color.web("#ffffff"));

        Label myNameLbl = new Label("my name is");
        myNameLbl.setAlignment(Pos.CENTER);
        myNameLbl.setFont(Font.font("Comic Sans MS", 48));
        myNameLbl.setStyle("-fx-background-color: red;padding: 20px;");
        myNameLbl.setTextFill(Color.web("#ffffff"));

        TextArea nameTxtArea = new TextArea();
        nameTxtArea.setWrapText(Boolean.TRUE);
        nameTxtArea.getStyleClass().add("center-text-area");
        nameTxtArea.setFont(Font.font("Comic Sans MS", 28));
        nameTxtArea.setStyle("padding: 20px;");

        Button printBtn = new Button("PRINT");
        printBtn.setId("ipad-grey");
        printBtn.setDisable(Boolean.TRUE);

        Button convertBtn = new Button("Convert Now!");
        convertBtn.setId("ipad-grey");
        convertBtn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                nameTxtArea.requestFocus();
                convertBtn.setDisable(Boolean.TRUE);
                printBtn.setDisable(Boolean.FALSE);
            }
        });

        HBox hBox = new HBox(100);
        hBox.setAlignment(Pos.CENTER);
        hBox.getChildren().addAll(convertBtn, printBtn);

        VBox vBox = new VBox(10);
        vBox.setAlignment(Pos.TOP_CENTER);
        vBox.getChildren().addAll(helloLbl, myNameLbl, nameTxtArea, hBox);
        vBox.setStyle("-fx-background-color: red;margin: 20px;");

        printBtn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                nameTxtArea.requestFocus();
                // Start printing
                print(vBox, nameTxtArea.getText());
                convertBtn.setDisable(Boolean.FALSE);
                printBtn.setDisable(Boolean.TRUE);
                nameTxtArea.setText("");
            }
        });

        Scene scene = new Scene(vBox);
        scene.getStylesheets().add(Main.class.getResource("/style.css").toExternalForm());

        primaryStage.setScene(scene);
        primaryStage.initStyle(StageStyle.UNDECORATED);
        primaryStage.setScene(scene);
        primaryStage.setX(visualBounds.getMinX());
        primaryStage.setY(visualBounds.getMinY());
        primaryStage.setWidth(visualBounds.getWidth());
        primaryStage.setHeight(visualBounds.getHeight());

        adjustTextAreaLayout(nameTxtArea);

        primaryStage.show();

        // attach keyboard to first node on scene:
        Node first = scene.getRoot().getChildrenUnmodifiable().get(0);
        if (first != null) {
            FXVK.init(first);
            FXVK.attach(first);
            keyboard = getPopupWindow();
        }

        nameTxtArea.focusedProperty().addListener((ob, b, b1) -> {
            if (keyboard == null) {
                keyboard = getPopupWindow();
            }

            keyboard.setHideOnEscape(Boolean.FALSE);
            keyboard.setAutoHide(Boolean.FALSE);
            keyboard.centerOnScreen();
            keyboard.requestFocus();

            keyboard.yProperty().addListener(obs -> {

                Platform.runLater(() -> {
                    Double y = bounds.getHeight() - taskbarHeight - keyboard.getY();
                    nameTxtArea.setMaxHeight((bounds.getHeight() - y) * 0.4);
                    nameTxtArea.setMinHeight((bounds.getHeight() - y) * 0.4);
                });
            });

        });     

    }

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

    private void print(Node node1, String text) {
        // Create a printer job for the default printer

        Printer printer = Printer.getDefaultPrinter();
        Paper label = PrintHelper.createPaper("2.5x3.5", 2.5, 3.5, Units.INCH);
        PageLayout pageLayout = printer.createPageLayout(label, PageOrientation.LANDSCAPE, Printer.MarginType.EQUAL);

        PrinterJob job = PrinterJob.createPrinterJob();

        Node node = createFullNode(text);

        double scaleX = pageLayout.getPrintableWidth() / node1.getBoundsInParent().getWidth();
        double scaleY = pageLayout.getPrintableHeight() / node1.getBoundsInParent().getHeight();
        node.getTransforms().add(new Scale(scaleX, scaleY));

        if (job != null) {
            // Print the node
            boolean printed = job.printPage(node);

            if (printed) {
                // End the printer job
                job.endJob();
            } else {
                // Write Error Message
                System.out.println("Printing failed.");
            }
        } else {
            // Write Error Message
            System.out.println("Could not create a printer job.");
        }

        node.getTransforms().remove(node.getTransforms().size() - 1);
    }

    private PopupWindow getPopupWindow() {

        @SuppressWarnings("deprecation") 
        final Iterator<Window> windows = Window.impl_getWindows();

        while (windows.hasNext()) {
            final Window window = windows.next();
            if (window instanceof PopupWindow) {
                if (window.getScene() != null && window.getScene().getRoot() != null) { 
                    Parent root = window.getScene().getRoot();
                    if (root.getChildrenUnmodifiable().size() > 0) {
                        Node popup = root.getChildrenUnmodifiable().get(0);
                        if (popup.lookup(".fxvk") != null) {
                            FXVK vk = (FXVK) popup.lookup(".fxvk");
                            // hide the key:
                            vk.lookup(".hide").setVisible(false);
                            return (PopupWindow) window;
                        }
                    }
                }
                return null;
            }
        }
        return null;
    }

    private Node createFullNode(String text) {

        Label helloLbl = new Label("Hello");
        helloLbl.setAlignment(Pos.CENTER);
        helloLbl.setFont(Font.font("Comic Sans MS", FontWeight.BOLD, 68));
        helloLbl.setStyle("-fx-background-color: red;padding: 20px;");
        helloLbl.setTextFill(Color.web("#ffffff"));

        Label myNameLbl = new Label("my name is");
        myNameLbl.setAlignment(Pos.CENTER);
        myNameLbl.setFont(Font.font("Comic Sans MS", 48));
        myNameLbl.setStyle("-fx-background-color: red;padding: 20px;");
        myNameLbl.setTextFill(Color.web("#ffffff"));

        TextArea nameTxtArea = new TextArea();
        nameTxtArea.setWrapText(Boolean.TRUE);
        nameTxtArea.setFont(Font.font("Comic Sans MS", 28));
        nameTxtArea.setStyle("padding: 20px;");
        nameTxtArea.setText(text);
        nameTxtArea.getStyleClass().add("center-text-area");

        HBox hBox = new HBox(1000);
        hBox.setAlignment(Pos.CENTER);

        VBox vBox = new VBox(10);
        vBox.setAlignment(Pos.CENTER);
        vBox.getChildren().addAll(helloLbl, myNameLbl, nameTxtArea, hBox);
        vBox.setStyle("-fx-background-color: red;margin: 20px;");

        vBox.getStylesheets().add(Main.class.getResource("/style.css").toExternalForm());

        return vBox;
    }

    private void adjustTextAreaLayout(TextArea textArea) {
        textArea.applyCss();
        textArea.layout();

        ScrollPane textAreaScroller = (ScrollPane) textArea.lookup(".scroll-pane");
        Text text = (Text) textArea.lookup(".text");


        ChangeListener<? super Bounds> listener = 
                (obs, oldBounds, newBounds) -> centerTextIfNecessary(textAreaScroller, text);
        textAreaScroller.viewportBoundsProperty().addListener(listener);
        text.boundsInLocalProperty().addListener(listener);

    }

    private void centerTextIfNecessary(ScrollPane textAreaScroller, Text text) {
        double textHeight = text.getBoundsInLocal().getHeight();
        double viewportHeight = textAreaScroller.getViewportBounds().getHeight();
        double offset = Math.max(0, (viewportHeight - textHeight) / 2 );
        text.setTranslateY(offset);
        Parent content = (Parent)textAreaScroller.getContent();
        for (Node n : content.getChildrenUnmodifiable()) {
            if (n instanceof Path) { // caret
                n.setTranslateY(offset);
            }
        }
    }
}

You can show and hide the virtual keyboard on demand.

You just need to provide a node that the keyboard will be attached to, and it doesn't need to be a TextField.

Obviously, you show the virtual keyboard for being able to type in your input control (TextField, TextArea,...), but I'll leave this part to you.

Without knowing your scene hierarchy, I'll just pick the first node on it:

@Override
public void start(Stage stage) {
    ...
    stage.setScene(scene);
    stage.show();

    // attach keyboard to first node on scene:
    Node first = scene.getRoot().getChildrenUnmodifiable().get(0);
    if (first != null) {
        FXVK.init(first);
        FXVK.attach(first);
    }
}

That will show the keyboard right after showing the stage.

If you want to programmatically close it at any point, you will just call:

FXVK.detach();

About hiding one of the keys of the keyboard, this is a little bit more tricky, since the keyboard is placed in a popup, so first of all you need to get a handle of it. But you can find already solutions for this, like this one.

The following snippet will look for the popup window. As for the deprecated method, on JavaFX 9 it will be a public method ( javafx.stage.Windows.getWindows() ).

private PopupWindow getPopupWindow() {

    @SuppressWarnings("deprecation") 
    final Iterator<Window> windows = Window.impl_getWindows();

    while (windows.hasNext()) {
        final Window window = windows.next();
        if (window instanceof PopupWindow) {
            if (window.getScene() != null && window.getScene().getRoot() != null) { 
                Parent root = window.getScene().getRoot();
                if (root.getChildrenUnmodifiable().size() > 0) {
                    Node popup = root.getChildrenUnmodifiable().get(0);
                    if (popup.lookup(".fxvk") != null) {
                        FXVK vk = (FXVK) popup.lookup(".fxvk");

                        return (PopupWindow) window;
                    }
                }
            }
            return null;
        }
    }
    return null;
}

Once you have the virtual keyboard instance, you will be able to find any of its nodes with lookups, based on their style classes. Luckily, all the keys have assigned the styleClass key , so you can easily interact with all of them. As for the particular key to hide the keyboard, this one also has special and hide style classes:

// hide the key:
vk.lookup(".hide").setVisible(false);

Full sample code:

public class FXVKAlwaysOn extends Application {

    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button();
        btn.setText("Say 'Hello World'");

        StackPane root = new StackPane();
        root.getChildren().add(btn);

        Scene scene = new Scene(root, 1280, 600);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();

        Node first = scene.getRoot().getChildrenUnmodifiable().get(0);
        if (first != null) {
            FXVK.init(first);
            FXVK.attach(first);
            getPopupWindow();
        }
    }

    private PopupWindow getPopupWindow() {

        @SuppressWarnings("deprecation") 
        final Iterator<Window> windows = Window.impl_getWindows();

        while (windows.hasNext()) {
            final Window window = windows.next();
            if (window instanceof PopupWindow) {
                if (window.getScene() != null && window.getScene().getRoot() != null) { 
                    Parent root = window.getScene().getRoot();
                    if (root.getChildrenUnmodifiable().size() > 0) {
                        Node popup = root.getChildrenUnmodifiable().get(0);
                        if (popup.lookup(".fxvk") != null) {
                            FXVK vk = (FXVK) popup.lookup(".fxvk");
                            // hide the key:
                            vk.lookup(".hide").setVisible(false);
                            return (PopupWindow) window;
                        }
                    }
                }
                return null;
            }
        }
        return null;
    }
}

永远在线

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM