Background color rendering issue with HTMLEditor JavaFX8

92 Views Asked by At

Problem : So basically the problem is that when I do change background color at 12pt font size and then I increase the font size to let's say 36pt then the background color is not properly rendered in HTMLEditor. Here is the video on action : Video showing how I generate the issue.

Here is the sample fxml file :

<?xml version="1.0" encoding="UTF-8"?>

 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.Tab?>
 <?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.web.HTMLEditor?>

<TabPane xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="AppController">
 <tabs>
  <Tab text="Editor">
     <content>
        <GridPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0">
          <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          </columnConstraints>
          <rowConstraints>
            <RowConstraints minHeight="10.0" prefHeight="366.0" vgrow="ALWAYS" />
          </rowConstraints>
           <children>
              <HTMLEditor fx:id="htmleditor" htmlText="&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body contenteditable=&quot;true&quot;&gt;&lt;/body&gt;&lt;/html&gt;" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS" />
           </children>
        </GridPane>
     </content>
  </Tab>
  <Tab text="Raw">
     <content>
        <GridPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0">
           <columnConstraints>
              <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
           </columnConstraints>
           <rowConstraints>
              <RowConstraints maxHeight="195.0" minHeight="10.0" prefHeight="34.0" vgrow="NEVER" />
              <RowConstraints minHeight="10.0" prefHeight="366.0" vgrow="ALWAYS" />
           </rowConstraints>
           <children>
              <ToolBar prefHeight="40.0" prefWidth="200.0">
                 <items>
                    <Button mnemonicParsing="false" onAction="#onRawHTMLButtonClick" text="Raw HTML" />
                    <Button mnemonicParsing="false" onAction="#onUpdateButtonClick" text="Update" />
                 </items>
              </ToolBar>
              <TextArea fx:id="rawHTMLViewer" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1" />
           </children>
        </GridPane>
     </content>
  </Tab>
</tabs>
</TabPane>

Here is the code for running the gui:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class App extends Application {

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

@Override
public void start(Stage primaryStage) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader();
    fxmlLoader.setLocation(App.class.getResource("/View/App.fxml"));
    Scene scene = new Scene(fxmlLoader.load(), 900, 600);
    primaryStage.setTitle("Basic HtmlEditor");
    primaryStage.setScene(scene);
    primaryStage.show();
}

}

What I have tried to solve the problem : So basically I tried to retrive webengine reference and from there I have extracted the webpage. Webpage has a method to refresh and it also has a method to force to repaint. But still it doesn't solve the problem. Here is the code of that : @FXML private HTMLEditor htmleditor;

@FXML
private TextArea rawHTMLViewer;
private WebEngine engine;
@Override
public void initialize(URL location, ResourceBundle resources) {
    Platform.runLater(() -> {
        engine = HTMLEditorUtility.findWebView(htmleditor).getEngine();
        int backgroundColorNodeIndex = 16;
        ColorPicker colorPicker = (ColorPicker) HTMLEditorUtility.findNthNodeOfTopToolBar(htmleditor, backgroundColorNodeIndex);
        colorPicker.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("Color has been changed");
            repaint();
        });

        ComboBox fontSizeComboBox = (ComboBox) HTMLEditorUtility.findNthNodeOfBottomToolBar(htmleditor, 2);
        fontSizeComboBox.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("Font size has been changed");
            repaint();
        });
    });
}

And here is the repaint method code :

private void repaint() {
    WebPage webPage = Accessor.getPageFor(engine);
    webPage.refresh(webPage.getMainFrame());
    webPage.forceRepaint();
}

Also I have read in this post that we may overcome the screen refreshing problem by changing scene size. I have tried that also but it doesn't solve the problem. Please if anyone know any solution to this.

Here is the HTMLEditorUtility.java code :

import javafx.scene.Node;
import javafx.scene.control.ToolBar;
import javafx.scene.web.HTMLEditor;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import lombok.NonNull;

import java.util.function.Function;

 /**
 * @author : Md. Ismail Hosen
 * @version : 1.0
 */

public class HTMLEditorUtility {

static final String TOP_TOOLBAR_SELECTOR = ".top-toolbar";
static final String BOTTOM_TOOLBAR_SELECTOR = ".bottom-toolbar";
static final String WEB_VIEW_SELECTOR = "WebView";

/**
 * @param htmlEditor from which top toolbar will be founded.
 * @return this return the top toolbar.
 */
public static ToolBar findTopToolBar(HTMLEditor htmlEditor) {
    return findToolBar(htmlEditor, TOP_TOOLBAR_SELECTOR);
}

/**
 * @param htmlEditor from which bottom toolbar will be founded.
 * @return this return the bottom toolbar.
 */
public static ToolBar findBottomToolBar(HTMLEditor htmlEditor) {
    return findToolBar(htmlEditor, BOTTOM_TOOLBAR_SELECTOR);
}

/**
 * @param htmlEditor from which Webview will be founded.
 * @return this return the webview of the HTMLEditor
 */
public static WebView findWebView(@NonNull HTMLEditor htmlEditor) {
    return (WebView) htmlEditor.lookup(WEB_VIEW_SELECTOR);
}

/**
 * @param htmlEditor      from which we need to find the toolbar
 * @param toolbarSelector this is the selector for finding the node
 * @return it returns the toolbar based on the selector
 */
private static ToolBar findToolBar(@NonNull HTMLEditor htmlEditor, String toolbarSelector) {
    Node node = htmlEditor.lookup(toolbarSelector);
    if (node instanceof ToolBar) {
        return (ToolBar) node;
    }
    return null;
}

/**
 * @param htmlEditor from which we need to find the node
 * @param N          node index(0 based)
 * @return This will return top tollbar node based on the index(N)
 */

public static Node findNthNodeOfTopToolBar(HTMLEditor htmlEditor, int N) {
    return findNthNodeOfToolBar(htmlEditor, N, HTMLEditorUtility :: findTopToolBar);
}

/**
 * @param htmlEditor from which we need to find the node
 * @param N          node index(0 based)
 * @return This will return bottom toolbar node based on the index(N)
 */

public static Node findNthNodeOfBottomToolBar(HTMLEditor htmlEditor, int N) {
    return findNthNodeOfToolBar(htmlEditor, N, HTMLEditorUtility :: findBottomToolBar);
}

/**
 * @param htmlEditor from which we need to find the node
 * @param N          node index(0 based)
 * @param nodeFinder (functional intrface to run the code based on the finding section)
 * @return This will return the node based on the nodeFinder method and index(N)
 */

private static Node findNthNodeOfToolBar(@NonNull HTMLEditor htmlEditor, int N,
                                         Function<HTMLEditor, ToolBar> nodeFinder) {
    ToolBar toolBar = nodeFinder.apply(htmlEditor);
    return toolBar.getItems().get(N);
}

/**
 * @param htmlEditor for which top tollbar details will be printed.
 */

public static void printTopToolbarNode(@NonNull HTMLEditor htmlEditor) {
    printToolBarNode(htmlEditor, HTMLEditorUtility :: findTopToolBar);
}

/**
 * @param htmlEditor for which bottom toolbar details will be printed.
 */
public static void printBottomToolbarNode(@NonNull HTMLEditor htmlEditor) {
    printToolBarNode(htmlEditor, HTMLEditorUtility :: findBottomToolBar);
}

private static void printToolBarNode(HTMLEditor htmlEditor, Function<HTMLEditor, ToolBar> nodeFinder) {
    ToolBar topToolBar = nodeFinder.apply(htmlEditor);
    final int[] positionIndex = {0};
    topToolBar.getItems().forEach((node -> {
        System.out.println("position Index : " + positionIndex[0]);
        positionIndex[0] += 1;
        System.out.println("Style Class : " + node.getStyleClass());
        System.out.println("Class Name : " + node.getClass().getName());
        System.out.println("Type Selector: " + node.getTypeSelector());
        System.out.println("");
    }));
}

/**
 * @param htmlEditor from which we need to find the webengine
 * @return Webengine of that given html editor
 */
public static WebEngine findWebEngine(@NonNull HTMLEditor htmlEditor) {
    WebView webView = HTMLEditorUtility.findWebView(htmlEditor);
    return webView.getEngine();
}

}
0

There are 0 best solutions below