Reputation:
In my FXML file I have
<Label text="%label.total" />
And in properties file I have
label.total=Total
However, I want to have Total:
on my screen. And not only for this label but for many labels which are in fxml file. I don't want to add :
to properties file because it seems to be wrong because here we must keep only strings for different languages.
Is it possible to combine anyhow "%label.total"
with ":"
? Or another solutions are used this case?
Upvotes: 3
Views: 745
Reputation: 209358
This seems like it should be easier than it is. The FXML loader has the resource bundle automatically in its namespace with the key resources
. If the resource bundle were a java.util.Map
, then
<Label text="${resources.labelText + ':'}$ />
would work (with the key in the properties file changed to labelText
). However, the FXMLLoader
doesn't treat a resource bundle the same way as it treats a map, so this just ends up looking for a getLabelText()
method in the resource bundle. It may be worth a feature request to allow accessing resource bundle properties in the same way as map properties.
So one potential solution is to copy the resource values you need into a map. The following works with your original properties file:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.util.HashMap?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<VBox xmlns:fx="http://javafx.com/fxml/1">
<fx:define>
<HashMap fx:id="resourceAccess"
labelTotal="%label.total"
/>
</fx:define>
<Label text="${resourceAccess.labelTotal + ':'}" />
</VBox>
Note that you can add as many properties into the same map as you need, just add additional attributes. This feels a bit artificial, but it works.
You could also do this in Java code when you load the FXML:
ResourceBundle resourceBundle = ResourceBundle.getBundle(...);
FXMLLoader loader = new FXMLLoader(getClass().getResource(...), resourceBundle);
Map<String, Object> resourceAccess = new HashMap<>();
for (String key : resourceBundle.keySet()) {
resourceAccess.put(key, resourceBundle.getObject(key));
}
loader.getNamespace().put("resourceAccess", resourceAccess);
Parent root = loader.load() ;
Then the FXML
<Label text="${resourceAccess.labelTotal + ':'}" />
will work without the <fx:define>
block. Again, though, this solution prohibits using .
in the resource keys (or at least you would have to translate them to something else in the Java code: resourceAccess.put(key.replaceAll("\\.","_"), resourceBundle.getObject(key));
or similar).
It is not immediately apparent that any of this is better than the (perhaps more obvious) workaround:
<HBox><Label text="%label.total"/><Label text=":"/></HBox>
Upvotes: 2