JavaFX - How to set Custom font to javaFX controls? [duplicate] - css

Firstly, I am quite a new guy in coding. I need to embed a font in my java FXML-based app and don't know how to do it. I have pasted the font, fontName.ttf in a "resources" folder in the root of the sources of my project, ie App/src/app/resources. I have set the CSS for the component (text) as
#text {
-fx-font-family: url(resources/fontName.ttf);
}
I have also tried adding inverted commas in the url, ie url("resources/fontName.ttf");, but it doesn't work. I have also set the CSS id for the component, so that can't be the problem. Is there any other working way to do so? I have seen http://fxexperience.com/2010/05/how-to-embed-fonts/, but it doesn't work since I have JDK 1.7 u21. Any ideas for a correct way to embed fonts?

Solution Approach
I updated the sample from Javafx How to display custom font in webview? to demonstrate using a custom true-type font in JavaFX controls styled using CSS.
Key points are:
Place the font in the same location as your application class and ensure your build system places it in your binary build package (e.g. application jar file).
Load the code font in your JavaFX code before you apply a style which uses it.
Font.loadFont(CustomFontApp.class.getResource("TRON.TTF").toExternalForm(), 10);
To use the custom font in a style class use the -fx-font-family css attribute and just reference the name of the font (e.g. in this case "TRON").
Create and load a stylesheet which defines the style classes.
Apply style classes to your controls.
Additional Information
If you are using Java 8, you may be interested in Use web(Google) fonts in JavaFX.
Font Collections
If your font file is in .ttc format, containing multiple fonts in a single file, then use the Font.loadFonts API (instead of Font.loadFont). Note that Font.loadFonts is only available since JDK 9 and is not available in earlier releases.
Sample Output Using a Custom Font
Sample Code
The example relies on a TRON.TTF font which you can download from dafont.
CustomFontApp.java
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.scene.text.*;
import javafx.stage.Stage;
// demonstrates the use of a custom font.
public class CustomFontApp extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) {
stage.setTitle("TRON Synopsis");
// load the tron font.
Font.loadFont(
CustomFontApp.class.getResource("TRON.TTF").toExternalForm(),
10
);
Label title = new Label("TRON");
title.getStyleClass().add("title");
Label caption = new Label("A sci-fi flick set in an alternate reality.");
caption.getStyleClass().add("caption");
caption.setMaxWidth(220);
caption.setWrapText(true);
caption.setTextAlignment(TextAlignment.CENTER);
VBox layout = new VBox(10);
layout.setStyle("-fx-padding: 20px; -fx-background-color: silver");
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(
title,
new ImageView(
new Image(
"http://ia.media-imdb.com/images/M/MV5BMTY5NjM2MjAwOV5BMl5BanBnXkFtZTYwMTgyMzA5.V1.SY317.jpg"
)
),
caption
);
// layout the scene.
final Scene scene = new Scene(layout);
scene.getStylesheets().add(getClass().getResource("custom-font-styles.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
}
custom-font-styles.css
/** file: custom-font-styles.css
* Place in same directory as CustomFontApp.java
*/
.title {
-fx-font-family: "TRON";
-fx-font-size: 20;
}
.caption {
-fx-font-family: "TRON";
-fx-font-size: 10;
}
On FXML Usage
Font.loadFont(url, size) is a static method taking two parameters. I don't think you can invoke font.loadFont from FXML and wouldn't advise it if you could. Instead, load the font in Java code (as I have done in my answer) before you load your FXML or style sheet which requires the font.

I know you didn't ask for a pure programmatic way to use a custom TTF font in a java fx application but i thought maybe it helps someone to see a programmatic version:
public class Test2 extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(final Stage primaryStage) {
Group rootGroup = new Group();
// create a label to show some text
Label label = new Label("Demo Text");
try {
// load a custom font from a specific location (change path!)
// 12 is the size to use
final Font f = Font.loadFont(new FileInputStream(new File("./myFonts/TRON.TTF")), 12);
label.setFont(f); // use this font with our label
} catch (FileNotFoundException e) {
e.printStackTrace();
}
rootGroup.getChildren().add(label);
// create scene, add root group and show stage
Scene scene = new Scene(rootGroup, 640, 480, Color.WHITE);
primaryStage.setScene(scene);
primaryStage.show();
}
}
That did the job for me. You can place the font wherever you want just make sure you adapt the path.
You can find a lot more about using fonts inside java fx apps here.
HTH

Related

How to change the icon size of a color picker in JavaFX?

How to change the icon size of a color picker in javaFX. I'm having a problem, I can not increase the icon size of a color picker in JavaFX, does anyone know how to change the size of the button icon?
icon its small :(
Setting the CSS attributes -fx-color-rect-width and -fx-color-rect-width will change size of the rectangle displayed. Setting fx-font-size will change the size of the arrow.
Note that some of these attributes are not documented in the official JavaFX CSS reference, so I guess future JavaFX iterations could change them without notice. Still, at this stage, I think that is probably unlikely and the attributes are pretty safe to use. To determine the undocumented CSS attributes, I looked at the source code for the ColorPickerSkin.
pickme.css
.large-rect-picker {
-fx-color-rect-width: 60px;
-fx-color-rect-height: 60px;
-fx-color-label-visible: false;
-fx-min-width: 150px;
-fx-min-height: 100px;
-fx-pref-width: 150px;
-fx-pref-height: 100px;
}
.large-rect-picker > .arrow-button {
-fx-font-size: 30px;
}
PickMe.java
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.stage.Stage;
public class PickMe extends Application {
#Override
public void start(Stage stage) {
ColorPicker colorPicker = new ColorPicker();
colorPicker.getStyleClass().add("large-rect-picker");
stage.setScene(new Scene(new Group(colorPicker)));
stage.getScene().getStylesheets().add(
PickMe.class.getResource(
"pickme.css"
).toExternalForm()
);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Aside info on asking questions
It is difficult to know exactly what you want as you aren't really explicit in the question. For instance what do you mean by icon? The rectangle or the down arrow or both? What about the display that is popped up when you click on that arrow, should that change at all or stay the same? For future questions, I recommend you be more specific about what you are trying to achieve and how it differs from what you have. Showing code which produces what you have might also help others solve your issue. Hopefully the info above is enough for you to modify it to accomplish what you wish.
You can access and customize color picker by using css:
ColorPicker
Style class: color-picker
Substructure
color display node — Label
arrow-button — StackPane
arrow — StackPane
The ColorPicker control has all the properties and pseudo‑classes of ComboBase
Example
.color-picker .label {
-fx-background-color: red;
-fx-text-fill: null;
-fx-graphic: url("1487868456_Other_Antivirus_Software.png");//This is icon of Color picker label
}
Result:
As far as I know you cant use -fx-width/-fx-height at all and you cant use percentage values for it. The width and height of elements are read-only. You can set -fx-pref-width, -fx-pref-height, -fx-max-width, -fx-min-width, -fx-max-height, -fx-min-height ,-fx-border-width and -fx-border-height to adjust the size of Java FX elements.
.picker-color {
-fx-border-color:white ;
-fx-border-width:40;
}

How to lookup the applied font on JavaFX Label?

I need to automatically resize the font on my JavaFX Label if the text doesn't all fit in the label's boundaries. I found some awesome code online (here Resize JavaFX Label if overrun) to do this but the problem is the code takes font size and as an argument. It seems like determining the font size would be very easy, but Label.getFont() returns the default settings because my application is using css to set the font sizes. My css is setting the font size to 30, but everything I have figured out how to look up on the Label so far is returning default settings of 12.
So I tried looking it up but I don't understand where to look for it. Label.getStyle() returns an empty string. getCSSMetaData() returns a whole bunch of interesting settings and I was able to find font there and look at the sub properties, but again it is storing the default values of font size 12 and a different style name.
This is the setting from my style sheet file that I'm using so I know I need to locate feedback card and font size:
._Feedback_Card {
-fx-font-size: 30px;
-fx-font-weight: bold;
-fx-text-fill: rgba(0,0,0,.9);
-fx-background-color: white;
-fx-border-color: white;
-fx-border-width: 0;
-fx-alignment: center;
-fx-text-alignment: center;
-fx-font-family: Arial Unicode MS;
-fx-effect: dropshadow(gaussian, #b4b4b4, 6,0,0,2);
}
Don't be swayed by the name, there's a mapping somewhere else in the code that maps this component to that class name somehow. It's written by a co-worker so I'm unaware of the exact mechanics. But given that name I tried looking up the region on the root node with:
Region node = (Region)jsLayoutCollection.jsDisplayLayoutCollection.fGetFXParent().lookup("._Feedback_Card");
String sStream = node.getCssMetaData().stream()
and then I looked through the stream for font properties. But that again returned font but the size was the default 12, not 30 that the style sheet sets it to.
So where is this property being applied and how do I look it up? It seems like it should be straightforward to figure out this information but I can't find it. It's very easy to set the font after with:
Label.setStyle("-fx-font-size: " + fontSize + "px");
Any help is greatly appreciated.
Once the stylesheet has been loaded by the label's scene (or parent), and CSS has been applied, getFont() will return the font set by CSS.
This code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class GetCSSFont extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Big label");
StackPane root = new StackPane(label);
Scene scene = new Scene(root);
scene.getStylesheets().add("set-font.css");
System.out.println("Default font: "+label.getFont());
label.applyCss();
System.out.println("Font from CSS: "+label.getFont());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
with set-font.css:
.label {
/* Note the font family needs quoting if it has spaces: */
-fx-font-family: 'Arial Unicode MS' ;
-fx-font-size: 30px ;
-fx-font-weight: bold ;
}
.root {
-fx-padding: 20 ;
}
produces the output:
Default font: Font[name=System Regular, family=System, style=Regular, size=13.0]
Font from CSS: Font[name=Arial Unicode MS, family=Arial Unicode MS, style=Regular, size=30.0]
(And you can, of course, get the point size with double size = label.getFont().getSize().)

Is there are any implementation of rectangle selection in javafx?

I mean like in file managers, when you would click, drag the mouse, creating a rectangle selection and after the mouse released selection is created?
I could do that like this (pseude-code like):
onMousePressed:
setGestureStarted(true)
onMouseMoved:
if isGestureStarted:
changeRectangle(event.getX, event.getY)
onMouseReleased:
select(getSelectionRectange())
But I thought that it's pretty common behavior and maybe it's already in framework.
EDIT1:
I was trying to do zoomable linechart. And I actually came across library to do that.
It's pretty good, but could be better though.
Right now I'm considering the actual worth of javaFX in our web project, because I don't like how such thing as zoomable chart is not in the library. Probably would be better with javascript (except I should learn it first, but It shouldn't be that hard).
You would probably need to make your own implementation for this. I found your pseudo code is quiet good. If you like to select for any component then you need to first create a simple rectangular boundary which is easily possible by your pseudo code.
Now for finding out either your node is inside that boundary then you need to do iteration of all the nodes/children of certain Parent Object by using this function: Node Intersect check
I would suggest to use that function after the onMouseReleased or if you like to see things in realtime then it is preferable in onMouseMoved
Your question asks "Is there any implementation of rectangle selection in JavaFX?"
The answer is "yes".
SceneBuilder implements drag-select functionality.
SceneBuilder is open source, so take a look through the source if you are interested on how this behaviour is achieved in JavaFX by SceneBuilder.
SceneBuilderKit is the framework from which SceneBuilder is derived, its source is at the link I provided.
From the SceneBuilder release notes:
JavaFX Scene Builder Kit is an API that allows the integration of Scene Builder panels and functionalities directly into the GUI of a larger application, or a Java IDE, such as NetBeans, IntelliJ, and Eclipse.
where is documentation?
From the release notes:
The javafx_scenebuilder_kit_javadoc-2_0-ea--.zip file, which contains an API javadoc for the JavaFX Scene Builder Kit. You can download the zip file from http://www.oracle.com/technetwork/java/javafx/downloads/devpreview-1429449.html.
The javafx_scenebuilder_kit_samples-2_0-ea--.zip file, which contains the SceneBuilderHello sample application that shows a minimal Java source code example of how the Scene Builder Kit API can be used. This sample is delivered as a NetBeans project. It can be downloaded from http://www.oracle.com/technetwork/java/javafx/downloads/devpreview-1429449.html.
Perhaps after you investigate, SceneBuilder and SceneBuilderKit might not be what you are looking for. In which case, edit your question to make it more explicit and perhaps include source for your rectangle selection implementation attempt and more detail on your requirements (what you intending to select, an image showing how the feature works, etc).
yes, in jfxtras-labs project via:
MouseControlUtil.addSelectionRectangleGesture(Parent root, Rectangle rect)
or
MouseControlUtil.addSelectionRectangleGesture(Parent root, Rectangle rect, EventHandler<MouseEvent> dragHandler, EventHandler<MouseEvent> pressHandler, EventHandler<MouseEvent> releaseHandler)
more info: http://jfxtras.org/doc/8.0labs/jfxtras/labs/util/event/MouseControlUtil.html
Note that selection behavior is extremely application specific and the class above is just a helper class to help you with selection gesture implementations. In the end you have to implement selection behavior yourself.
For a more detailed and matured example of node selection in JavaFx see my other answer here.
Edit: Basic Demo
This is the basic usage. Note that it's just a demo and should NOT be considered final or production ready! For more complex implementation of selection behavior you should tailor it (mostly mouse handlers) on your own based on your application's specific requirements.
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import jfxtras.labs.util.event.MouseControlUtil;
public class ShapeSelectionExample extends Application {
private List<Shape> selected = new ArrayList<>();
#Override
public void start(Stage primaryStage) {
final Group shapesGroup = new Group();
final AnchorPane root = new AnchorPane(shapesGroup);
// Add whatever shapes you like...
Rectangle shape1 = new Rectangle(200, 20, 50, 50);
Rectangle shape2 = new Rectangle(300, 60, 50, 50);
Circle shape3 = new Circle(100, 100, 30);
shapesGroup.getChildren().addAll(shape1, shape2, shape3);
final Rectangle selectionRect = new Rectangle(10, 10, Color.TRANSPARENT);
selectionRect.setStroke(Color.BLACK);
EventHandler<MouseEvent> mouseDragHanlder = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
for (Node shape : shapesGroup.getChildren()) {
handleSelection(selectionRect, (Shape) shape);
}
}
};
// Add selection gesture
MouseControlUtil.addSelectionRectangleGesture(root, selectionRect, mouseDragHanlder, null, null);
primaryStage.setScene(new Scene(root, 400, 300));
primaryStage.show();
}
private void handleSelection(Rectangle selectionRect, Shape shape) {
if(selectionRect.getBoundsInParent().intersects(shape.getBoundsInParent())) {
shape.setFill(Color.RED);
if(!this.selected.contains(shape))
this.selected.add(shape);
} else {
shape.setFill(Color.BLACK);
this.selected.remove(shape);
}
System.out.println("number of selected items:" + this.selected.size());
}
public static void main(String[] args) {
launch(args);
}
}
This is how the result would look like:
You could also write mouse press and release handlers (currently null in this code) to handle selection behavior while mouse button is pressed or released (which is different to mouse drag).

Javafx How to display custom font in webview?

The web page uses a custom font which is not installed on my PC. In such case, WebView seems to use the default font of the operation system.
But I have the font file "xx.ttf". How can I embed the font into my application and tell WebView to use it to identify the font on the page?
Load the font:
Font.loadFont(
CustomFontWebView.class.getResource("TRON.TTF").toExternalForm(),
10
);
before you use it in the WebView:
style='font-family:"TRON"';
Here is a complete example.
The example relies on a TRON.TTF font which you can download from dafont.
Once you have downloaded the TRON.TTF font, place it in the same directory as CustomFontWebView.java and ensure that your build system copies the TRON.TTF file to the class output directory.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
// demonstrates the use of a custom font in a WebView.
public class CustomFontWebView extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) {
stage.setTitle("TRON Synopsis");
// load the tron font.
Font.loadFont(
CustomFontWebView.class.getResource("TRON.TTF").toExternalForm(),
10
);
// use the tron font in a WebView.
WebView webView = new WebView();
webView.getEngine().loadContent(
"<body bgcolor='silver'>" +
"<div align='center'>" +
"<p style='font-family:'TRON'; font-size:20;'>" + "TRON" +
"</p>" +
"<img src='http://ia.media-imdb.com/images/M/MV5BMTY5NjM2MjAwOV5BMl5BanBnXkFtZTYwMTgyMzA5.V1.SY317.jpg' width='259' height='457'/>" +
"<p style='font-family:'TRON'; font-size:10;'>" +
"A sci-fi flick set in an alternate reality." +
"</p>" +
"</div>" +
"</body>"
);
// layout the scene.
final Scene scene = new Scene(webView, 400, 575);
stage.setScene(scene);
stage.show();
}
}
On use of the Microsoft YaHei font specifically
Microsoft YaHei works fine for me (Windows 7). My Win7 install comes with the font (and it can't be removed), so it doesn't need to be explicitly loaded - just reference the correct font family from your html and it will just work for such a Win7 install. I have a standard US edition of Win7 Pro, not a Chinese version. I did copy the msyh.ttf file from my windows/fonts directory into my project and load it via JavaFX just to make sure the loading via JavaFX works and that also worked fine. The font-family I used to set the html style css font-family specifier was "Microsoft YaHei" (instead of TRON used in the above answer example). The text I displayed to test it was 微软雅黑 and I compared the rendered text by the JavaFX app against the same text rendered in WordPad with Microsoft YaHei selected and the glyphs were identical.
Note that with JavaFX 3.0 is seems you will be able to use the css #font-face mechanism, which means you could declare the font reference in the web page's css rather than in Java code as I did in the above example. Here is a link to the relevant jira issue to track progress on implementation of this feature.

How to center/wrap/truncate Text to fit within Rectangle in JavaFX 2.1?

I need to dynamically create Rectangles over Pane in JavaFX 2.1. Next I need to center/wrap/truncate Text over the Rectangle. The text has to fit within the rectangle. I am able to center and wrap the text with the following code, however, if the text length is too long, it will appear out of the rectangle. I want to create the behavior like Label within StackPane, essentially if the Rectangle grows, the Text will grow with it but always remain in the center of the Rectangle and if the Text cannot fit within the Rectangle, it will be truncated accordingly.
Rectangle r;
Text t;
...
//center and wrap text within rectangle
t.wrappingWidthProperty().bind(rect.widthProperty().multiply(0.9);
t.xProperty().bind(rect.xProperty().add(rect.widthProperty().subtract(t.boundsInLocalProperty().getValue().getWidth().divide(2)));
t.yProperty().bind(rect.yProperty().add(rect.heightProperty().divide(2)));
t.setTextAlignment(TextAlignment.CENTER);
t.setTextOrigin(VPos.CENTER);
What properties can I use to achieve that or is there a better way of doing this?
Here is a sample alternate implementation.
It uses a subclass of Group with a layoutChildren implementation rather than the binding api.
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.geometry.VPos;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.*;
import javafx.stage.Stage;
public class TextInRectangle extends Application {
public static void main(String[] args) throws Exception { launch(args); }
public void start(final Stage stage) throws Exception {
TextBox text = new TextBox("All roads lead to Rome", 100, 100);
text.setLayoutX(30);
text.setLayoutY(20);
final Scene scene = new Scene(text, 160, 140, Color.CORNSILK);
stage.setScene(scene);
stage.show();
}
class TextBox extends Group {
private Text text;
private Rectangle rectangle;
private Rectangle clip;
public StringProperty textProperty() { return text.textProperty(); }
TextBox(String string, double width, double height) {
this.text = new Text(string);
text.setTextAlignment(TextAlignment.CENTER);
text.setFill(Color.FORESTGREEN);
text.setTextOrigin(VPos.CENTER);
text.setFont(Font.font("Comic Sans MS", 25));
text.setFontSmoothingType(FontSmoothingType.LCD);
this.rectangle = new Rectangle(width, height);
rectangle.setFill(Color.BLACK);
this.clip = new Rectangle(width, height);
text.setClip(clip);
this.getChildren().addAll(rectangle, text);
}
#Override protected void layoutChildren() {
final double w = rectangle.getWidth();
final double h = rectangle.getHeight();
clip.setWidth(w);
clip.setHeight(h);
clip.setLayoutX(0);
clip.setLayoutY(-h/2);
text.setWrappingWidth(w * 0.9);
text.setLayoutX(w / 2 - text.getLayoutBounds().getWidth() / 2);
text.setLayoutY(h / 2);
}
}
}
Sample output of the sample app:
A couple of notes:
It is usually best to use a Label rather than trying to recreate part of a Label's functionality.
The layout in layoutChildren approach is a similar to that used by the JavaFX team in implementing the JavaFX control library. There are probably reasons they use layoutChildren rather than binding for layout, but I am not aware of what all of those reasons are.
I find for simple layouts, using the pre-built controls and layout managers from the JavaFX library is best (for instance the above control could have been implemented using just a Label or Text in StackPane). Where I can't quite get the layout I need from the built-in layouts, then I will supplement their usage with bindings, which I find also very easy to work with. I don't run into the need to use layoutChildren that much. It's probably just a question of scaling up to lay out complex node groups - most likely doing the calculations in the layoutChildren method performs better and may be easier to work with and debug when applied to complex node groups.
Rather than truncating Text by calculating a text size and eliding extra characters from a String as a Label does, the code instead calls setClip on the text node to visually clip it to the rectangle's size. If instead you would like to truncate Text more like a Label, then you could look at the code for the JavaFX utility class which does the computation of clipped text.
The sample code in the question does not compile because it is missing a bracket on the wrappingWidthProperty expression and it uses getValue and getWidth methods inside a bind expression, which is not possible - instead it needs to use a listener on the boundsInLocalProperty.
Also, created a small sample app demoing adding text placed in a Label with a rectangular background to a Pane with precise control over the x,y position of the labeled rectangle via binding.

Resources