ADDITIONAL SYSTEM INFORMATION :
Windows 10 Enterprise 21H1 (19043.1237)
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)
One screen with a Windows scaling of 125%
A DESCRIPTION OF THE PROBLEM :
Layouting of JavaFX components rely on proper values for renderScaleX and renderScaleY of the stage. If the scale is 1.0 instead of 1.25, then images and text looks blurry after scaled by the operating system.
When the JavaFX scene is set before it is really shown, then those scale factors are not properly propagated to the EmbeddedWindow.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use any Windows display with a scaling of 125% and start the attached test case (using SET_FRAME_VISIBLE_LATE set to true, i.e. setScene() is called before frame.setVisibile()).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The text should be 125% and the filled rectangular box shows only black pixels, including all pixels that are part of the edges.
ACTUAL -
The text is 100% and the pixels at the edges are gray instead of black.
---------- BEGIN SOURCE ----------
package de.empic.openjfx;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
public class Main
{
private static final boolean SET_FRAME_VISIBLE_LATE = true;
private static void initAndShowGUI()
{
JFrame frame = new JFrame("Swing and JavaFX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if (!SET_FRAME_VISIBLE_LATE)
{
setFrameVisible(frame);
}
Platform.runLater(() -> initFX(fxPanel, frame));
}
private static void initFX(JFXPanel fxPanel, JFrame frame)
{
// This method is invoked on the JavaFX thread
Scene scene = createScene();
fxPanel.setScene(scene);
if (SET_FRAME_VISIBLE_LATE)
{
SwingUtilities.invokeLater(() -> setFrameVisible(frame));
}
}
private static void setFrameVisible(JFrame frame)
{
frame.setVisible(true);
}
private static Scene createScene()
{
VBox root = new VBox();
root.setPadding(new Insets(5));
Scene scene = new Scene(root);
HBox hBox = new HBox();
hBox.setPrefSize(30, 30);
hBox.setMaxWidth(Region.USE_PREF_SIZE);
hBox.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)));
Label label = new Label();
scene.windowProperty().addListener((ob, oldWindow, newWindow) ->
{
newWindow.renderScaleXProperty().addListener((obs, oldValue, newValue) -> updateText(label, newValue));
updateText(label, newWindow.getRenderScaleX());
});
root.getChildren().addAll(hBox, label);
return (scene);
}
private static void updateText(Label label, Number scaleX)
{
if (scaleX == null)
{
label.setText("Unknown scale x");
}
else
{
label.setText(String.format("%.0f%%", scaleX.doubleValue() * 100));
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(Main::initAndShowGUI);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Change the order of setScene() and setVisible(true).
FREQUENCY : always
Windows 10 Enterprise 21H1 (19043.1237)
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)
One screen with a Windows scaling of 125%
A DESCRIPTION OF THE PROBLEM :
Layouting of JavaFX components rely on proper values for renderScaleX and renderScaleY of the stage. If the scale is 1.0 instead of 1.25, then images and text looks blurry after scaled by the operating system.
When the JavaFX scene is set before it is really shown, then those scale factors are not properly propagated to the EmbeddedWindow.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use any Windows display with a scaling of 125% and start the attached test case (using SET_FRAME_VISIBLE_LATE set to true, i.e. setScene() is called before frame.setVisibile()).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The text should be 125% and the filled rectangular box shows only black pixels, including all pixels that are part of the edges.
ACTUAL -
The text is 100% and the pixels at the edges are gray instead of black.
---------- BEGIN SOURCE ----------
package de.empic.openjfx;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
public class Main
{
private static final boolean SET_FRAME_VISIBLE_LATE = true;
private static void initAndShowGUI()
{
JFrame frame = new JFrame("Swing and JavaFX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if (!SET_FRAME_VISIBLE_LATE)
{
setFrameVisible(frame);
}
Platform.runLater(() -> initFX(fxPanel, frame));
}
private static void initFX(JFXPanel fxPanel, JFrame frame)
{
// This method is invoked on the JavaFX thread
Scene scene = createScene();
fxPanel.setScene(scene);
if (SET_FRAME_VISIBLE_LATE)
{
SwingUtilities.invokeLater(() -> setFrameVisible(frame));
}
}
private static void setFrameVisible(JFrame frame)
{
frame.setVisible(true);
}
private static Scene createScene()
{
VBox root = new VBox();
root.setPadding(new Insets(5));
Scene scene = new Scene(root);
HBox hBox = new HBox();
hBox.setPrefSize(30, 30);
hBox.setMaxWidth(Region.USE_PREF_SIZE);
hBox.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)));
Label label = new Label();
scene.windowProperty().addListener((ob, oldWindow, newWindow) ->
{
newWindow.renderScaleXProperty().addListener((obs, oldValue, newValue) -> updateText(label, newValue));
updateText(label, newWindow.getRenderScaleX());
});
root.getChildren().addAll(hBox, label);
return (scene);
}
private static void updateText(Label label, Number scaleX)
{
if (scaleX == null)
{
label.setText("Unknown scale x");
}
else
{
label.setText(String.format("%.0f%%", scaleX.doubleValue() * 100));
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(Main::initAndShowGUI);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Change the order of setScene() and setVisible(true).
FREQUENCY : always