Can anyone please help me with wrapping the text in a legend of a javafx chart. I have pie charts and bar charts. All the legends are placed at bottom. I tried the following but couldn't get it working.
for (Node node : pie.lookupAll(".chart-legend")) {
if (node instanceof Text) {
System.out.println("Text instance");
((Text) node).setWrappingWidth(380);
((Text) node).setManaged(true);
}
if (node instanceof Label) {
System.out.println("Label instance");
((Label) node).setWrapText(true);
((Label) node).setManaged(true);
((Label) node).setPrefWidth(380);
}
}
EDIT:
See the highlighted part. Still some text is not visible.
I finally got it. Trying to wrap text in css didn't work as label width cannot be controlled there. So the following code can be used to wrap the text programmatically.
for (Node node : pie.lookupAll(".chart-legend-item")) {
if (node instanceof Label) {
System.out.println("Label instance");
((Label) node).setWrapText(true);
((Label) node).setManaged(true);
((Label) node).setPrefWidth(380);
}
}
Did you have a look at the CSS documentation?
This link is refering to the chart legend section:
JavaFX CSS Reference
As mentioned, it's of the type Label, so we can have a look here as well.
-fx-wrap-text possibly does the trick. Of course you would need to write and attach your own CSS file to your program...
For a more detailed example, please refer to your JDKs jfxrt.jar, unzip it and look for the modena.css, which is the default CSS file.
Regards.
Daniel
Edit: I got the following snipped to actually have an impact on or application after all:
.chart-legend {
-fx-background-color: transparent;
-fx-padding: 20px;
}
.chart-legend-item-symbol {
-fx-background-radius: 0;
}
.chart-legend-item {
-fx-text-fill: #191970;
}
But it is important, where you place it in your CSS. In my first attempt, I placed it above the CSS rule, which set the default label text color.
When I noticed this, I put it at the end of my CSS file: et vóila - it worked.
So please have a second look, that your placed accordingly in your own CSS.
Related
I am working on a Javafx application and I tried to add some Labels, Buttons and Texts, which resizes when the user resizing the Scene. All Nodes are inside a VBox, which itself is inside a StackPane.
My test application:
public class Test extends Application
{
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(final Stage primaryStage)
{
StackPane pane = new StackPane();
VBox box = new VBox();
box.setAlignment(Pos.CENTER);
Label l = new Label("Label");
Text t = new Text("Text");
t.getStyleClass().add("test");
Button b = new Button("Button");
pane.heightProperty().addListener(listener ->
{
double h = pane.getHeight()/5;
l.setFont(Font.font(l.getFont().getFamily(), h));
t.setFont(Font.font(t.getFont().getFamily(), h));
b.setFont(Font.font(b.getFont().getFamily(), h));
});
box.getChildren().addAll(l, t, b);
pane.getChildren().add(box);
primaryStage.setScene(new Scene(pane));
primaryStage.getScene().getStylesheets().add(Path.of("test.css").toUri().toString());
primaryStage.show();
}
}
If I resize the Stage it works as expected. But unfortunately only with pure Java code.
Because after adding my css file, the Labeled controls behave different. While the Text elements continue to change in size, the Labels and Buttons does not change their size anymore.
My css file, which does not work:
.label
{
-fx-text-fill: red;
-fx-font-family: impact;
}
.test
{
-fx-fill: red;
-fx-font-family: impact;
-fx-font-size: 2em;
}
.button
{
-fx-text-fill: red;
-fx-font-size: 2em;
}
I asked myself what I did wrong and have tested different css states. I found out, when I omit font values in css it works, otherwise it does not. Therewhile it does not matter which font value occurs, only one font value is required to miss the behavior.
My css file, which works:
.label
{
-fx-text-fill: red;
//-fx-font-family: impact;
}
.test
{
-fx-fill: red;
-fx-font-family: impact;
-fx-font-size: 2em;
}
.button
{
-fx-text-fill: red;
//-fx-font-size: 2em;
}
1. Question: -has changed, see below-
Do I missunderstand something about css and Javafx, or did I something wrong in my css file or is there a bug?
2. Question: -solved-
Have I to put the font values with java code or is there an other way to add the font?
Thank You for helping!
Update
As recommended I have studying the follow guide:
https://openjfx.io/javadoc/14/javafx.graphics/javafx/scene/doc-files/cssref.html
The JavaFX CSS implementation applies the following order of precedence:
The implementation allows designers to style an application by using style sheets to override property values set from code. For example, a call to rectangle.setFill(Color.YELLOW) can be overridden by an inline‑style or a style from an author stylesheet. This has implications for the cascade; particularly, when does a style from a style sheet override a value set from code? The JavaFX CSS implementation applies the following order of precedence: a style from a user agent style sheet has lower priority than a value set from code, which has lower priority than a Scene or Parent style sheet. Inline styles have highest precedence. Style sheets from a Parent instance are considered to be more specific than those styles from Scene style sheets.
In my case this means, I will use the inline style to make it proper.
thus the 2. Question is solved
But, because of Parent style sheet > value set from code, it also means, all Nodes are not allowed to change theire size, even the Text Node.
Therefore I changed my 1. Question to:
Why does the JavaFX CSS order of precedence differ between Text and Controls
Question 1:
It's not a bug, it's a conflict of priorities. .setFont() has a lower priority than that CSS. Just replace .setFont() to .setStyle() and sample will work as you planned:
l.setStyle("-fx-font-size:" + h + ";");
t.setStyle("-fx-font-size:" + h + ";");
b.setStyle("-fx-font-size:" + h + ";");
Question 2:
Try to keep all about styles in CSS. It's the best practice.
I'm trying to implement a TinyMCE button that will apply the style of the selection to the entire box. I'm having trouble, though, reading the style of the selection when the selection is buried in a span in a span in a paragraph. Let's consider 'color' for example. Below I have a box with some text and I've selected "here" in the paragraph and made it red.
The HTML for the paragraph is now:
The code behind my button to apply the style of the selection to the box is
var selected_color = $(ed.selection.getNode()).css('color');
console.log("color pulled is ", selected_color);
$(ed.bodyElement).css('color', selected_color);
It doesn't work because the color pulled is black, not red, so the third line just re-applies the black that's already there. (If I replace selected_color in the third line with 'blue' everything goes blue.) So the problem is pulling the color of the current selection.
Does anyone know how I can do this reliably, no matter how buried the selection is?
Thanks for any help.
I also noticed somewhat a strange behavior up and there, with selections of nested span's and div's, but honestly i'm not able to recognize if this is a bug of TinyMCE, a browser issue or a combination of both (most probably).
So, waiting for some more information from you (maybe also your plugin code) in the meanwhile i realized two proposal to achieve what you want: the first plugin behaves like the format painter in word, the second is simply applying the current detected foreground color to the whole paragraph.
As you move throug the editor with the keyboard or mouse, you will see the current detected foreground color highlighted and applied as background to the second plugin button.
Key point here are two functions to get the styles back from the cursor position:
function findStyle(el, attr) {
var styles, style, color;
try {
styles = $(el).attr('style');
if(typeof styles !== typeof undefined && styles !== false) {
styles.split(";").forEach(function(e) {
style = e.split(":");
if($.trim(style[0]) === attr) {
color = $(el).css(attr);
}
});
}
} catch (err) {}
return color;
}
function findForeColor(node) {
var $el = $(node), color;
while ($el.prop("tagName").toUpperCase() != "BODY") {
color = findStyle($el, "color");
if (color) break;
$el = $el.parent();
}
return color;
}
The try...catch block is needed to avoid some occasional errors when a selected text is restyled. If you look at the TinyMCE sorce code you will notice a plenty of timing events, this is a unavoidable and common practice when dealing with styles and css, even more with user interaction. There was a great job done by the authors of TinyMCE to make the editor cross-browser.
You can try out the first plugin in the Fiddle below. The second plugin is simpler as the first one. lastForeColor is determined in ed.on('NodeChange'), so the code in button click is very easy.
tinymce.PluginManager.add('example2', function(ed, url) {
// Add a button that opens a window
ed.addButton('example2', {
text: '',
icon: "apply-forecolor",
onclick: function() {
if(lastForeColor) {
var applyColor = lastForeColor;
ed.execCommand('SelectAll');
ed.fire('SelectionChange');
ed.execCommand('forecolor', false, applyColor);
ed.selection.collapse(false);
ed.fire('SelectionChange');
}
return false;
}
});
});
Moreover: i think there is a potential issue with your piece of code here:
$(ed.bodyElement).css('color', selected_color);
i guess the style should be applied in a different way, so in my example i'm using standard TinyMCE commands to apply the foreground color to all, as i wasn't able to exactly convert your screenshot to code. Please share your thoughts in a comment.
Fiddle with both plugins: https://jsfiddle.net/ufp0Lvow/
deblocker,
Amazing work! Thank you!
Your jsfiddle did the trick. I replaced the HTML with what was in my example and changed the selector in tinymce.init from a textarea to a div and it pulls the color out perfectly from my example. The modified jsfiddle is at https://jsfiddle.net/79r3vkyq/3/ . I'll be studying and learning from your code for a long time.
Regarding your question about
$(ed.bodyElement).css('color', selected_color);
the divs I attach tinymce to all have ids and the one the editor is currently attached to is reported in ed.bodyElement. I haven't had any trouble using this but I have no problem using your
ed.execCommand('SelectAll');
ed.fire('SelectionChange');
ed.execCommand('forecolor', false, applyColor);
Thanks again! Great job!
There is an option to bind CSS files to add style to JavaFX components.
But I want to change some properties dynamically in code.
There is a setStyle() method but there is not enough documentation available on using it.
I want to change the hover color from the setStyle() method instead of the .css file.
Here is the code for the .css file
.list-cell:filled:hover
{
-fx-background-color: #0093ff;
-fx-text-fill: white;
}
and I want to change the hover color from the setStyle() method dynamically like this:
noteListView.setStyle(
":filled:hover{" +
"-fx-background-color: #65ffb0;" +
"-fx-text-fill: white;" +
"}");
But this does not work. Any help is appreciated. Thanks.
Why don't you try something like that, I used it to change the color of a specific serie on a chart which be selected from a tableview.
table.getSelectionModel().selectedIndexProperty().addListener( (observable, oldValue, newValue) -> changeId(oldValue, newValue));
public void changeId(Number oldV, Number newV){
if(oldV.intValue() != -1){
lineChart.getData().get(oldV.intValue()).getNode().setId("serie-unselect");
}
if(newV.intValue() != -1){
lineChart.getData().get(newV.intValue()).getNode().setId("serie-select");
}
}
Then in the css file, you add #serie-select{} and #serie-unselect{} with good options.
I would like to provide for user possiblity to select color of TextArea:
private void updateTextArea(){
textArea.setStyle("-fx-text-fill: #" + textColor + "; -fx-background-color: #" + backgroundColor);
}
however this doesnt change color of whole background. Ive found on the Internet that to change backgroud of text Area I need to do something like this in external CSS file.
.text-area .content {
-fx-background-color: black ;
}
how Can I do this with setStyle()?
You can do this by fetching the content node out of the TextArea and applying the style to it. But it works only after the TextArea is shown on the stage.
Usage :
Node node = textArea.lookup(".content");
node.setStyle("-fx-background-color: black;");
I'm having a flickering issue with a text control.
Here's the context:
I have a title which is represented by a Text control (no Label cause it needs to be able to be displayed in several lines). When the user rolls over the title, the text has to be underlined.
What I have done:
I've set listeners to the title's rollover and rollout events to something like this:
private function titleHandler(e : MouseEvent) : void {
switch(e.type) {
case MouseEvent.ROLL_OVER:
_title.styleName = 'accessoriesTitleHover';
break;
case MouseEvent.ROLL_OUT:
_title.styleName = 'accessoriesTitle';
break;
}
}
Issue:
The title is flickering every time the stylename is changed (I would even say that the title disappears and reappears)
Alternative solutions I've tried:
changing the underline property using setStyle (doesn't work)
defining .accessoriesTitle and .accessoriesTitle:hover styles in the CSS, but the hover doesn't work =(
Would anyone know a solution or workaround this flickering thing?
Thanks for your time and help!! :)
Regards,
BS_C3
Sorry for the delay, here's the declaration of both styles:
.accessoriesTitle{
font-size: 13pt;
text-decoration: none;
leading: 1pt;
}
.accessoriesTitleHover{
font-size: 13pt;
text-decoration: underline;
leading: 1pt;
}
Regards
try this one
private function titleHandler(e : MouseEvent) : void {
switch(e.type) {
case MouseEvent.ROLL_OVER:
_title.setStyle('styleName', 'accessoriesTitleHover');
break;
case MouseEvent.ROLL_OUT:
_title.setStyle('styleName', 'accessoriesTitle');
break;
}
}
If this is not work reply immidiately.
Thanks
I found a "hack" to fix this problem.
Without the hack, it would seem that the text was emptied before being rendered again with the underlined style. The same goes when the text goes from an underlined style to a no text decoration style.
The text was either changing its size (from current size to 0 and then to new size) or emptying the content before rendering it again.
So I set the text height and here's what I get:
private function titleHandler(e : MouseEvent) : void {
switch(e.type) {
case MouseEvent.ROLL_OVER:
_title.height = _title.height;
_title.styleName = 'accessoriesTitleHover';
break;
case MouseEvent.ROLL_OUT:
_title.styleName = 'accessoriesTitle';
break;
}
}
And everything's working fine :)
Thanks for ur time.
Regards,
BS_C3