setFont() method not working on label as expected javafx - java

I am creating a short javafx program containing a label with some text and a button which is supposed to change the font of the label to italic. Since the font I use is a custom font, I can't directly call new Font("human.ttf", FontPosture.ITALIC, 20) as javafx can't convert a custom font to italic or bold.
So I decided to have two different font files with the same font family with one having regular style and the other having italic style. Thus, when the italic button is clicked, the program would load the italic font file and set the font of the label to be the italic font.
But when I tried the program, the font of the label remains unaffected after clicking the italic button. I tried hard to find the source of the issue and added several print statements. During the process I found the problem was that the setFont method in the eventHandler of the button was not working correctly. Due to the print statements I also found that the font file path was correct. Hence, I am unable to figure out my mistake in the code.
This is the FontChanger class:
public class FontChanger extends Application{
private Label label;
private Font font;
public void start(Stage primaryStage){
AnchorPane root = new AnchorPane();
root.setPrefHeight(30);
root.setPrefWidth(30);
addLabel(root);
addItalicButton(root);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
}
public void addLabel(AnchorPane root){
label = new Label("Sample text");
font = Font.loadFont(FontChanger.this.getClass().getResource("human.ttf").toExternalForm (), 20);
label.setFont(font);
label.setLayoutX(10);
label.setLayoutY(10);
root.getChildren().add(label);
}
public void addItalicButton(AnchorPane root){
Button italicButton = new Button("italic");
italicButton.setLayoutX(10);
italicButton.setLayoutY(35);
italicButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
font = Font.loadFont(FontChanger.this.getClass().getResource("human_italic.ttf").toExternalForm(), 20);
System.out.println(FontChanger.this.getClass().getResource("human_italic.ttf").to ExternalForm());
label.setFont(font);
}
});
root.getChildren().add(italicButton);
}
public static void main(String[] args){
launch(args);
}
}
Please tell me if any kind of clarification is needed. Thanks in advance.

Finally after hours of experimentation, I have found that the problem is that whenever the font of a label or any similar control is already set to a custom font, you cannot set it once again to another custom font. I don't know the reason why this happens.
You cannot do this:
public void setFont(){
Font firstCustomFont = Font.loadFont(FontChanger.this.getClass().getResource("firstCustomFont.ttf").toExternalForm(), 20);
label.setFont(firstCustomFont);
Font secondCustomFont = Font.loadFont(FontChanger.this.getClass().getResource("secondCustomFont.ttf").toExternalForm(), 20);
label.setFont(secondCustomFont);// this will not work
}
I also found that you could set the font of a label to be a normal font after setting it to a custom font. And also you could set the font to a custom font if it is already set to a local font.
These two examples will work:
public void setFont(){
Font customFont = Font.loadFont(FontChanger.this.getClass().getResource("customFont.ttf").toExternalForm(), 20);
label.setFont(customFont);
Font normalFont = Font.font(20);
label.setFont(normalFont);// this will work
}
And:
public void setFont(){
Font normalFont = Font.font(20);
label.setFont(normalFont);
Font customFont = Font.loadFont(FontChanger.this.getClass().getResource("customFont.ttf").toExternalForm(), 20);
label.setFont(customFont);// this will work
}
So the trick I applied is that I first set the font of the label to a local font and then setting the font once again to the custom font you want to be set.
Something like this:
public void setFont(){
Font firstCustomFont = Font.loadFont(FontChanger.this.getClass().getResource("firstCustomFont.ttf").toExternalForm(), 20);
label.setFont(font);
Font normalFont = Font.font(20);
label.setFont(normalFont);
Font secondCustomFont = Font.loadFont(FontChanger.this.getClass().getResource("secondCustomFont.ttf").toExternalForm(), 20);
label.setFont(secondFont);// this will work
}
Edit: This problem occurred because the font files I used were the edited versions of the same font family. So this method could work pretty well if you have a regular and styled version of a font file and then you want to apply the styled version to a text which is already set to the regular version.

Related

JavaFX: Text in button not centered when using custom font

I want to use the "Another Danger" font in my project. However JavaFX isn't quite liking it. Labels and buttons seem to estimate the height of the letters wrong and take a completely wrong size.
I wrote a simple example illustrating the problem:
public class HelloApplication extends Application {
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage stage) {
Button button = new Button("Test");
Scene scene = new Scene(button, 320, 240);
button.setFont(Font.loadFont(HelloApplication.class.getResourceAsStream("/fonts/AnotherDanger-Demo.otf"), 30));
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
}
The text in the button is clearly not centered. However, when I remove the custom font everything works perfectly. Is this a problem with the font? And if so is there any way to fix this?
I'd be very thankful for any help here.
EDIT: Here are screeshots as requested:
With the font:
Without the font:

How to display white text with a black background?

I am trying to figure out why my text isn't being displayed here. I assume it isn't being colored white, and simply doesn't show up against the black background. So, I'm trying to figure out why the background is being colored black, but the text isn't being shown.
I am using JavaFX 12.
How can I color the letters white?
public class MCVE extends Application {
private static Stage gameStage = new Stage();
#Override
public void start(Stage primaryStage) {
gameStage.setScene(new Scene(createScreen(), 1280.0, 800.0));
// adjust window settings.
gameStage.setTitle("my game");
gameStage.setResizable(false);
gameStage.show();
}
private Pane createScreen() {
Text welcome = new Text("Welcome,");
welcome.setFont(new Font("Old_Style", 22.0));
welcome.setStyle("-fx-text-fill: whitesmoke");
Text toMyGame = new Text(" to my game.");
toMyGame.setFont(new Font("System", 14.0));
toMyGame.setStyle("-fx-text-fill: whitesmoke");
TextFlow tf = createTextFlow();
ObservableList list = tf.getChildren();
list.addAll(welcome, toMyGame);
return tf;
}
private TextFlow createTextFlow() {
String style = "-fx-background-color: black;";
style += " -fx-text-fill: whitesmoke;";
TextFlow tf = new TextFlow();
tf.setStyle(style);
return tf;
}
}
-fx-text-fill is a CSS property of Labeled, not Text. Text is a type of shape, and Shape supports -fx-fill rather than -fx-text-fill.
Changing every occurrence of -fx-text-fill to -fx-fill should give you the appearance you want.

Multilne text. Libgdx

How to crate a multiline text? I tried to use Label , but text have only 1 line.
Table table = new Table();
table.setPosition(0,0);
table.setSize(800,440);
label = new Label("Some long string here...", skin);
label.setFillParent(true);
label.setAlignment(center);
label.setPosition(0,0);
label.setWidth(40);
label.setHeight(label.getPrefHeight());
label.setText(tutortext);
table.addActor(label);
stage.addActor(table);
stage.setDebugAll(true);
https://i.stack.imgur.com/3whQr.png
Use setWrap(true); on label.
According to doc.
If false, the text will only wrap where it contains newlines (\n). The preferred size of the label will be the text bounds.
If true, the text will word wrap using the width of the label. The preferred width of the label will be 0, it is expected that something external will set the width of the label. Wrapping will not occur when ellipsis is enabled. Default is false.
When wrap is enabled, the label's preferred height depends on the width of the label. In some cases the parent of the label will need to layout twice: once to set the width of the label and a second time to adjust to the label's new preferred height.
I've tested with small example :
public class MultiLine extends ApplicationAdapter {
Stage stage;
Skin skin;
#Override
public void create() {
stage=new Stage();
skin=new Skin(Gdx.files.internal("skin/glassy-ui.json"));
Label label=new Label("MULTILINE IN LIBGDX GAME DEVELOPMENT",skin);
label.setWrap(true);
Table table=new Table();
table.setFillParent(true);
table.add(label).width(150);
stage.addActor(table);
}
#Override
public void render() {
Gdx.gl.glClearColor(0,0,0,0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
stage.act();
}
#Override
public void dispose() {
stage.dispose();
skin.dispose();
}
}
Here is the output :
A way simpler solution is to just use \n for linebreaks so instead of
Label label=new Label("MULTILINE IN LIBGDX GAME DEVELOPMENT",skin);
you would just do
Label label=new Label("MULTILINE\nIN\nLIBGDX\nGAME\nDEVELOPMENT",skin);
The label will be:
MULTILINE
IN
LIBGDX
GAME
DEVELOPMENT

Assigning JavaFX Label Font from Combobox not working

I am trying to assign the font of a label(node) by selecting the value from a combobox I constructed. The combobox has only a few options, so all of them should be safe to use in this app.
Everything works fine, and all the correct string value from the combobox is being pulled and assigned to the label. But the font in the label doesn't change, and when I output the font from the label the active font is still the system default. I have another method that edits only the fontSize, and that works fine. So it must be the actual string value being invalid. But no error is thrown, and the combobox list names were gotten from the installed fonts on the system.
The Use case and the code is below. What am I missing?
1) Select Font and Click OK changed)
2) Assigned to label (Code snippets)
String font = String.valueOf(combobox_font.getValue());
label.setFont(Font.font(font));
Note: For the sake of my program I'm trying to assign font type and size separately, but I also tried assigning the values with the font size with no luck.
label.setFont(Font.font(font, fontSize)); ///fontSize is a double value gotten from teh textfled above
3) Outbut Label Font (Still System Default)
Font[name=System Regular, family=System, style=Regular, size=12.0]
If you are specifying the font name instead of the family name, you need to use the constuctor of Font, since all the static methods expect the font family:
#Override
public void start(Stage primaryStage) {
ComboBox<String> fontChoice = new ComboBox<>(FXCollections.observableList(Font.getFontNames()));
Spinner<Integer> spinner = new Spinner<>(1, 40, 12);
Text text = new Text("Hello World!");
text.fontProperty().bind(Bindings.createObjectBinding(() -> new Font(fontChoice.getValue(), spinner.getValue()), spinner.valueProperty(), fontChoice.valueProperty()));
HBox hBox = new HBox(fontChoice, spinner);
StackPane.setAlignment(hBox, Pos.TOP_CENTER);
StackPane root = new StackPane(hBox, text);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
To use the static methods, use the family names:
#Override
public void start(Stage primaryStage) {
ComboBox<String> familyChoice = new ComboBox<>(FXCollections.observableList(Font.getFamilies()));
Spinner<Integer> spinner = new Spinner<>(1, 40, 12);
Text text = new Text("Hello World!");
text.fontProperty().bind(Bindings.createObjectBinding(() -> Font.font(familyChoice.getValue(), spinner.getValue()), spinner.valueProperty(), familyChoice.valueProperty()));
HBox hBox = new HBox(familyChoice, spinner);
StackPane.setAlignment(hBox, Pos.TOP_CENTER);
StackPane root = new StackPane(hBox, text);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}

Strange issue with JLabel HTML rendering

I have the following really simple code for creating a JLabel and adding it to a panel using a MigLayout layout manager:
MigLayout layout = new MigLayout();
JPanel panel = new JPanel(layout);
panel.setBackground(Color.GRAY);
JLabel label = new JLabel("<html><h3>Some Text</h3></html>");
panel.add(label, "growx,w 220!,h 40!,top");
This should render the label as transparent so that the panel background is visible behind the label - this is the behaviour we want.
However on some PCs the label is rendered with a solid white background - ie as if opaque=true has been set.
Curiously, this isn't a problem if the label text is not formatted using html.
JLabel label = new JLabel("Some text");
We are using BasicLabelUI as the UI delegate so I would expect to see standard painting behaviour here.
This is running using jre 1.6.0_30 in Windows XP. Has anyone seen something like this before? Could it be something to do with differences between the graphics hardware running on the various machines?
I've worked out what was happening after taking some time away from the problem.
It's to do with Stylesheets and HTMLEditorKit.
Assume the following sample css:
body {
background-color: #ffff00}
The following code simple loads this into an new HTMLEditorKit instance, then adds a non-opaque html label to a panel.
public class HTMLLabelTest extends JFrame {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
JFrame frame = new HTMLLabelTest();
frame.pack();
frame.setVisible(true);
}
});
}
public HTMLLabelTest() {
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
StyleSheet styleSheet = new StyleSheet();
URL resource = getClass().getResource("/stylesheet.css");
styleSheet.importStyleSheet(resource);
htmlEditorKit.setStyleSheet(styleSheet);
JLabel label = new JLabel();
label.setText("<html><B>Some HTML Formatted</B> text</html>");
label.setOpaque(false);
label.setHorizontalAlignment(JLabel.CENTER);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setPreferredSize(new Dimension(30,20));
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(label);
panel.setOpaque(true);
panel.setBackground(Color.WHITE);
add(panel);
setPreferredSize(new Dimension(300,200));
}
}
Once imported, the stylesheet is made available to subsequent instances of HTMLEditorKit, such as the one being used to render the label. So in the code sample, the non-opaque label is shown with a yellow background.
If you create the label before installing the styles in the example, the label (and subsequent labels) will not pick up the style and be rendered non-opaque as desired.
The problem we have is that our application can be launched both separately and from within another app (running in the same jre). Some users of the second app have access to a screen that installs a stylesheet before our app can be launched. In these instances the styles are loaded and stored as defaults ready to be used by our app. This is why some users reported a problem and others didn't.
I haven't decided on the best solution for this yet. One possibility was to override the background style when creating the label html:
<html><body bgcolor=\"red\">Test</body></html>
However, if you use 'transparent' instead of a solid colour, the underlying colour from the stylesheet is shown instead. Annoying!
The fact JLabel hasn't been overriden is not relevant as all the painting is delegated to an instanceof ComponentUI, i.e. the look and feel. This will vary between environments.

Categories