Blurred text in JavaFX TextArea

2020-04-02 07:15发布

问题:

I am having a weird issue with JavaFX. I designed a simple Scene in SceneBuilder. The text looks ok in a preview, but in the running the app the text looks blurred, consider the following image. Here is the FXML:

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>

<AnchorPane id="AnchorPane" fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="br.mviccari.javafxtest.controllers.TelaMensagemController">
  <children>
    <TitledPane alignment="CENTER_LEFT" animated="false" collapsible="false" contentDisplay="LEFT" prefHeight="400.0" prefWidth="600.0" text="Janela legal" textAlignment="LEFT" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <content>
        <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
          <children>
            <HBox id="HBox" alignment="CENTER" spacing="5.0" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="14.0">
              <children>
                <Button mnemonicParsing="false" onAction="#acaoFodase" prefHeight="53.9609375" prefWidth="128.0" text="Foda-se" />
                <Button mnemonicParsing="false" onAction="#acaoOk" prefHeight="53.9609375" prefWidth="128.0" text="OK" />
              </children>
            </HBox>
            <TextArea fx:id="campoTexto" disable="false" editable="true" focusTraversable="true" prefHeight="278.0" prefWidth="570.0" rotate="0.0" text="Aqui vai um texto padrão motherfucker!" wrapText="true" AnchorPane.bottomAnchor="82.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="14.0" />
          </children>
        </AnchorPane>
      </content>
    </TitledPane>
  </children>
</AnchorPane>

And here is the application class code:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/br/mviccari/javafxtest/layouts/telaMensagem.fxml"));
Parent root = fxmlLoader.load();
TelaMensagemController controller = fxmlLoader.getController();
controller.setParametroDeTeste("PIKACHU EU ESCOLHO VC!");
controller.init();
Stage stage = new Stage(StageStyle.DECORATED);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(labelStatus.getScene().getWindow());
stage.setOpacity(1);
stage.setTitle("My New Stage Title");
stage.setScene(new Scene(root, 450, 450));
stage.showAndWait();

I have tried to run the app using JDK 7, this way the text is not blurred anymore, but how can I run it with JDK 8 showing a normal text

I have put my project on bitbucket, if anyone tries to see the code or checkout to your machine, you can see this on your own

https://mateusviccari@bitbucket.org/mateusviccari/testejavafx.git

回答1:

I have figured out a solution for this issue. I was able to ascertain that the issue is centered around a bug introduced in JavaFX 8 which causes some blurriness of the content displayed within a ScrollPane when said ScrollPane has decimal value constraints, the bug has to do with the cached image of the content so turning off caching works. TextAreas make use of ScrollPanes.

textArea.setCache(false);
ScrollPane sp = (ScrollPane)textArea.getChildrenUnmodifiable().get(0);
sp.setCache(false);
for (Node n : sp.getChildrenUnmodifiable()) {
    n.setCache(false);
}


回答2:

If someone has a similar problem inside PopOver from ControlsFX: Blurred text inside text controls (WebView, TextArea, etc).

The solution is to override the -fx-stroke-width attribute inside the .popover > .border selector:

.popover > .border { -fx-stroke-width: 1; }

Example:

val popOver = PopOver()
val webView = WebView()
webView.engine.loadContent("<html>Some text that should be not blurred</html>")
popOver.contentNode = webView
popOver.root.stylesheets.add(this.javaClass.getResource("test.css").toString())


var b = Button("Press")
val scene = Scene(StackPane(b), 800.0, 600.0)

b.onAction = EventHandler { popOver.show(b) }

primaryStage.scene = scene
primaryStage.show()



回答3:

I've noticed SceneBuilder 1.1 made me a css file with

.text {
    -fx-font-smoothing-type: lcd; 
} 

I haven't played around with it but the Oracle says

LCD (liquid crystal display) text is an anti-aliased text that takes advantage of the properties of LCD panels to render smoother text. You can take advantage of the LCD text on the text nodes by using the API shown in Example 11.

text.setFontSmoothingType(FontSmoothingType.LCD));



回答4:

I can't say why the text is blur, maybe it is because of the font used, or styles applied. But that difference in your image is coming from the different versions of JavaFX used in. SceneBuilder is using the JavaFX 2 while executed one is using javaFX 8. Configure your Java environment to use the same version.

Determine the version used like as:

primaryStage.setTitle(com.sun.javafx.runtime.VersionInfo.getRuntimeVersion());

On my Windows 8 machine the text in text area shown as follow without blurring. Note the version numbers in titles:



回答5:

I had a similar issue with the blurry text. Using JavaFX Scene Builder, I noticed that under Layout: Position, I had Layout X / Y a non zero value (like 9.893739 etc). when I replaced those with 0, the blurry text went away.



标签: java javafx