Javafx ImageView Tooltip style - css

I have made a global style to be applied to all tooltips, and it is working correctly except when then the tooltip is installed onto an ImageView. If I add the tooltip to the ImageView's parent (a HBox), the styling is correct, so it can't be a problem with the stylesheet not being added.
The css style looks like this:
.tooltip
{
-fx-border-color: gray;
-fx-border-radius: 5.0 5.0 5.0 5.0;
-fx-background-radius: 5.0 5.0 5.0 5.0;
-fx-background-color: white;
-fx-text-fill: black;
-fx-wrap-text: true;
}
Adding tooltip to imageview (style doesn't work):
Tooltip.install(imageviewFormat, formatTooltip);
Adding tooltip to parent (style does work):
Tooltip.install(imageviewFormat.getParent(), formatTooltip);
Am I doing something stupid here, or does ImageView not inherit the css from its parent. Any insight would be appreciated.
Update
The following example has this behavior, where style.css contains the same tooltip styleclass.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Test extends Application
{
public static void main(String[] args) throws Exception
{
launch(args);
}
#Override
public void start(Stage primarystage) throws Exception
{
HBox root = new HBox();
root.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
ImageView imageView = new ImageView("http://www.samjarman.co.nz/images/so.png");
root.getChildren().add(imageView);
Tooltip.install(imageView, new Tooltip("Tooltip")); // Doesn't work
// Tooltip.install(imageView.getParent(), new Tooltip("Tooltip")); // Works
Scene scene = new Scene(root);
primarystage.setScene(scene);
primarystage.show();
}
}
Thanks

Related

JavaFX - setStyle() changes not showing

I am creating a JavaFX application and I am having problems changing the background colors for certain components. For the buttons I am able to change their background radius, but not their background color. For the TableView I am unable to change the background color as well.
Here is my code and a picture of what I am seeing.
import javafx.geometry.Pos;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableView;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class HomeUI extends Application {
private TableView transactionTable = new TableView();
private Button importButton = new Button("Import");
private Button trendButton = new Button("Trends");
private Button transactionButton = new Button("Transactions");
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
// Set the text of defined fields
primaryStage.setTitle(" Budget Tracker");
// Import button information
// Create Anchor pane
AnchorPane anchorPane = new AnchorPane();
anchorPane.setPrefHeight(668.0);
anchorPane.setPrefWidth(1112.0);
anchorPane.setStyle("-fx-background-color: #545e75;");
// VBox to hold all buttons
VBox vBox = new VBox();
vBox.setPrefWidth(195);
vBox.setPrefHeight(668);
vBox.prefHeight(668);
vBox.prefWidth(203);
vBox.setStyle("-fx-background-color: #82a0bc;");
vBox.setLayoutX(0);
vBox.setLayoutY(0);
vBox.setAlignment(Pos.CENTER);
// importButton settings
importButton.setMnemonicParsing(false);
importButton.setPrefWidth(300);
importButton.setPrefHeight(80);
importButton.setStyle("-fx-background-color: #cacC9cc");
importButton.setStyle("-fx-background-radius: 0;");
// trendButton settings
trendButton.setPrefWidth(300);
trendButton.setPrefHeight(80);
trendButton.setStyle("-fx-background: #bcbdc1");
trendButton.setStyle("-fx-background-radius: 0");
// transactionButton settings
transactionButton.setPrefWidth(300);
transactionButton.setPrefHeight(80);
transactionButton.setStyle("-fx-base: #aeacb0");
transactionButton.setStyle("-fx-background-radius: 0");
// Add buttons to the vBox
vBox.getChildren().addAll(importButton, trendButton, transactionButton);
// TableView settings
transactionTable.setPrefHeight(568);
transactionTable.setPrefWidth(694);
transactionTable.setLayoutX(247);
transactionTable.setLayoutY(50);
transactionTable.setStyle("-fx-background-color: CAC9CC;");
transactionTable.setEditable(false);
// Add components to anchorPane
anchorPane.getChildren().addAll(vBox, transactionTable);
// Add anchorPane to scene and show it
primaryStage.setScene(new Scene(anchorPane));
primaryStage.show();
}
}
Buttons
By setting the style property, you replace the old style. Doing this multiple times does not combine the styles. You should set a value that combines the rules.
Instead of
transactionButton.setStyle("-fx-base: #aeacb0");
transactionButton.setStyle("-fx-background-radius: 0");
use
transactionButton.setStyle("-fx-base: #aeacb0; -fx-background-radius: 0;");
TableView
TableView shows little of it's own background. Most coloring you'll see is the background color of the TableRows that are added as descendants of the TableView. You'll need to use a CSS stylesheet to do this though (unless you want to use a rowFactory to do the styling).
.table-view .table-row-cell {
-fx-background-color: #CAC9CC;
}

Disable spacing between items in TextFlow in JavaFX

I'm trying to make a line of text which consists of a name and a string of text. I want the name to be a hyperlink and the rest to be just plain text.
I thought TextFlow would be good for this, but the problem is it automatically puts a single space between the hyperlink and the text. What if I want the TextFlow to be for example
Jane's awesome
The TextFlow will make that a
Jane 's awesome
Is there a method or CSS property to disable this behaviour?
Solution
You can remove the padding via a CSS style:
.hyperlink {
-fx-padding: 0;
}
Or you can do it in code if you wish:
link.setPadding(new Insets(0));
Background
The default setting can be found in the modena.css file in the jfxrt.jar file packaged with your JRE distribution and it is:
-fx-padding: 0.166667em 0.25em 0.166667em 0.25em; /* 2 3 2 3 */
Sample application
In the sample screenshot the second hyperlink has focus (hence its dashed border).
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class HyperSpace extends Application {
#Override
public void start(Stage stage) {
TextFlow textFlow = new TextFlow(
unstyle(new Hyperlink("Jane")),
new Text("'s awesome "),
unstyle(new Hyperlink("links"))
);
stage.setScene(new Scene(new Pane(textFlow)));
stage.show();
}
private Hyperlink unstyle(Hyperlink link) {
link.setPadding(new Insets(0));
return link;
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX apply rotate to an image from CSS

I'm wondering if there is a way to apply some transformations (i.e. rotate) to an image setted to some button. I am using css to specify all images by such way:
.custom-button {
-fx-graphic: url("imgs/buttons/button.png");
...
}
.custom-button:hover {
-fx-graphic: url("imgs/buttons/button_hover.png");
...
}
.custom-button:selected {
-fx-graphic: url("imgs/buttons/button_selected.png");
...
}
I want to specify such transformation here in css as well.
How can I achieve that? I am supposing to find something like:
.custom-button .graphic {
-fx-rotate: 90;
}
Let's start with an example application:
Main.java
package application;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Button");
VBox vBox = new VBox(button);
vBox.setPadding(new Insets(10.0));
Scene scene = new Scene(vBox, 200, 100);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
System.out.println();
}
public static void main(String[] args) {
launch(args);
}
}
application.css
.button {
-fx-graphic: url(image.png);
}
Result
Method 1 (find out which class is used for the image)
This can be easily done using a debugger (set a breakpoint on println() and check the content of button.graphic.value). The class which is used here is ImageView. This means the image can be rotated using:
.button .image-view {
-fx-rotate: 45;
}
Result
Method 2 (set a custom class for the graphic object)
This can be done using a ChangeListener:
button.graphicProperty().addListener((ChangeListener<Node>) (observable, oldValue, newValue) -> {
newValue.getStyleClass().add("my-class");
});
Then the following can be used to rotate the image:
.my-class {
-fx-rotate: 45;
}
Result
Padding
You might need to add additional padding to the button, if the image takes up too much space:
.button {
-fx-graphic: url(image.png);
-fx-graphic-text-gap: 10;
-fx-label-padding: 5 0 5 5;
}
Result

how about css class prescedence in javafx

I want to add another css class for my component by example
.item{
-fx-background-color:blue;
-fx-border-radius:5;
}
.item-some{
-fx-background-color:red;
}
and in my code
control.getStyleClass().addAll("item","item-some");
but my control only get "item-some" style i want override only the color applying the second class as in css on web, can someone help me or give me a link to read about it?
thanks.
This basically behaves as expected for me: the item with both style classes gets the properties defined for both selectors. If there are conflicts, such as fx-background-color in this example, the one defined later in the css file overrides the ones before it.
Here's a complete test:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
public class MultipleStyleClassTest extends Application {
#Override
public void start(Stage primaryStage) {
Region region1 = new Region();
Region region2 = new Region();
region1.getStyleClass().add("style-class-1");
region2.getStyleClass().addAll("style-class-1", "style-class-2");
HBox root = new HBox(region1, region2);
Scene scene = new Scene(root);
scene.getStylesheets().add("multiple-style-class-test.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
multiple-style-class-test.css is
.style-class-1 {
-fx-min-width: 300 ;
-fx-min-height: 400 ;
-fx-background-color: blue ;
-fx-background-radius: 25 ;
}
.style-class-2 {
-fx-background-color: red ;
}
and the result is
As can be seen, both region1 and region2 get the -fx-min-height, -fx-min-width, and -fx-background-radius properties defined for style-class-1. region1 gets the -fx-background-color defined for style-class-1; region2 displays the background color defined for style-class-2.

Set Graphic to label

I want to set Label to graphic. I tested this code:
private static final ImageView livePerformIcon;
static
{
livePerformIcon = new ImageView(MainApp.class.getResource("/images/Flex.jpg").toExternalForm());
}
final Label label = new Label();
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
livePerformIcon.setFitHeight(20);
livePerformIcon.setFitWidth(20);
label.setGraphic(livePerformIcon);
But I don't see any image.
The only way that I found to make it work is this:
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
Is there a way to solve this?
Not sure, but AFAIK controls should be created on the JavaFX Application thread, but you're creating ImageView in a static initializer, which I'm not sure if it's executed on the Application thread.
Besides: Do you really want livePerformIcon to be static???
This one made from the data used in the docs, works perfectly for me
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class LabelWithImages extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Label With Image Sample");
stage.setWidth(400);
stage.setHeight(180);
HBox hbox = new HBox();
//Replace the image you want to put up
Image image = new Image(getClass().getResourceAsStream("a.png"));
Label label = new Label("Demo Label");
label.setGraphic(new ImageView(image));
hbox.setSpacing(10);
hbox.getChildren().add((label));
((Group) scene.getRoot()).getChildren().add(hbox);
stage.setScene(scene);
stage.show();
}
}
Code snippets below will set the value of the property graphic of a label. You can use any of the two. I prefer using javafx css, just to implement the model-view-controller design.
// programmatically, provided with image input stream
label.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("path/to/image.png"))));
// javafx css, provided with image url
.label {
-fx-graphic: url("path/to/image.png");
}

Resources