ScrollPane containing ImageView does not update its scrollbars after calling setImage() - javafx

I am experimenting JavaFX with a simple image viewer. I want it to display an image and, if it does not fit in the window, display scrollbars. The image to dislay is loaded with the FileChooser and set to the ImageView using imageView.setImage(image).
The problem is that the scrollbars of the containing ScrollPane do not update after calling imageView.setImage(image). Instead, I need to perform an action that changes the scene (e.g. resize the window). It behaves the same when an image is displayed and another is loaded, i.e. the sizes of the scrollbars reflect the size of the previous image.
The bug is reproducible using the following cut-down version of the code:
(Java)
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class ImageViewerBug extends Application
{
#FXML private ImageView imageView;
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ImageViewerBug.fxml"));
fxmlLoader.setController(this);
try {
BorderPane borderPane = (BorderPane) fxmlLoader.load();
Scene scene = new Scene(borderPane);
primaryStage.setScene(scene);
primaryStage.show();
}
catch( IOException e ) {
throw new RuntimeException(e);
}
}
public void loadClicked() {
FileChooser fileChooser = new FileChooser();
File f = fileChooser.showOpenDialog(null);
if( f != null ) {
try( InputStream is = new FileInputStream(f) ) {
Image image = new Image(is);
imageView.setImage(image);
}
catch( IOException e ) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
launch(args);
}
}
(FXML)
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.Group?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<BorderPane id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<center>
<ScrollPane prefHeight="200.0" prefWidth="200.0">
<content>
<Group>
<ImageView fx:id="imageView" pickOnBounds="true" preserveRatio="true" />
</Group>
</content>
</ScrollPane>
</center>
<top>
<ToolBar>
<items>
<Button mnemonicParsing="false" onAction="#loadClicked" text="Load" />
</items>
</ToolBar>
</top>
</BorderPane>

I can confirm this bug. A quick and dirty workaround that fixed it for me:
public void loadClicked() {
FileChooser fileChooser = new FileChooser();
File f = fileChooser.showOpenDialog(null);
if( f != null ) {
try( InputStream is = new FileInputStream(f) ) {
Image image = new Image(is);
imageView.setImage(image);
imageView.snapshot(new SnapshotParameters(), new WritableImage(1, 1));
double rnd = new Random().nextInt(10);
imageView.setX(rnd/1000);
imageView.setY(rnd/1000);
}
catch( IOException e ) {
e.printStackTrace();
}
}
}
The snapshot() Method sometimes works like a charm whenever some UI-element isn't updated or displayed correctly. But don't ask me why that works, maybe it has something to do with the rendering process, because snapshots forces JavaFX to render the scene graph or the target elements. The random stuff is needed to create the right scrollbar sizes when adding a new image after one already part of the ImageView.
Maybe this has something to do with the strange behaviour i found some weeks earlier. The workaround also solved my problems back then.
(Really late)EDIT
The problem is caused by the Group which wraps the ImageView. If you use a node that inherits from Pane the behaviour of the ScrollPane should be as expected even without the workaround. A Group can still be used as the direct child of the ScrollPane as long as a Pane wraps the ImageView.
Example:
<ScrollPane prefHeight="200.0" prefWidth="200.0">
<content>
<Group id="Group">
<children>
<HBox id="HBox" alignment="CENTER" layoutX="0.0" layoutY="0.0" spacing="5.0">
<children>
<ImageView fx:id="imageView" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
</children>
</Group>
</content>
</ScrollPane>

I have had the same problem with image...Instead of
Image image = new Image(is);
You should write:
Image image = new Image("file:" + ABSOLUTE_PATH_TO_FILE);
Image will refresh automatically, you don't have to do anything. For me, it works

use the command:
Scrollbar scrollbar
// ...
// Some activities with children that extends canvas, so scrollbar is needed.
// ...
scrollbar.layout();
this will update your scrollbar.
No Workaround needed.

Related

javafx button positoning in scene

how can I set a button's position in the middle for all size of anchorpane in javafx scenebuilder.....
like this code...
the button should be in the middle even if i set the scene into the middle
i have tried so many times but couldent get it...
thanks in advance
if you dont understand try to run the code in IDE and then maximize it and again minimize it...
observe the position of the button
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.*;
import javafx.stage.WindowEvent;
import java.util.Optional;
public class Javafxpopupmessage extends Application {
private Stage mainStage;
#Override
public void start(Stage stage) throws Exception {
this.mainStage = stage;
stage.setOnCloseRequest(confirmCloseEventHandler);
Button closeButton = new Button("Close Application");
closeButton.setOnAction(event ->
stage.fireEvent(
new WindowEvent(
stage,
WindowEvent.WINDOW_CLOSE_REQUEST
)
)
);
StackPane layout = new StackPane(closeButton);
layout.setPadding(new Insets(100));
stage.setScene(new Scene(layout));
stage.show();
}
private EventHandler<WindowEvent> confirmCloseEventHandler = event -> {
Alert closeConfirmation = new Alert(
Alert.AlertType.CONFIRMATION,
"Are you sure you want to exit?"
);
Button exitButton = (Button)
closeConfirmation.getDialogPane().lookupButton(
ButtonType.OK
);
exitButton.setText("Exit");
closeConfirmation.setHeaderText("Confirm Exit");
closeConfirmation.initModality(Modality.APPLICATION_MODAL);
closeConfirmation.initOwner(mainStage);
// normally, you would just use the default alert positioning,
// but for this simple sample the main stage is small,
// so explicitly position the alert so that the main window can still be
seen.
closeConfirmation.setX(mainStage.getX());
closeConfirmation.setY(mainStage.getY() + mainStage.getHeight());
Optional<ButtonType> closeResponse = closeConfirmation.showAndWait();
if (!ButtonType.OK.equals(closeResponse.get())) {
event.consume();
}
};
public static void main(String[] args) {
launch(args);
}
}
This can not be done directly in AnchorPane because positions are fixed there. You must use a container that allows "floating positioning". For example HBox.
<AnchorPane xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Button text="Exit" />
</children>
</HBox>
</children>
</AnchorPane>

Javafx: How can I code the calculation to get results when I click the button?

package javafx_tipcalc;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import java.text.NumberFormat;
public class JavaFX_TipCalc extends Application {
// declare interface controls
// declare labels
Label titleLabel, checkAmtLabel, tipPercentLabel, splitLabel;
Label tipAmtLabel, totalLabel, amtPerPersonLabel;
// declare text fields
TextField checkAmtText, tipAmtText, totalText, amtPerPersonText;
// declare a slider
Slider tipPercentSlider;
// declare a choice box
ChoiceBox splitChoiceBox;
// declare a button
Button calcTipButton;
// declare currency and percent formatter
NumberFormat currency = NumberFormat.getCurrencyInstance();
NumberFormat persent = NumberFormat.getCurrencyInstance();
// declare a grid pane (8 rows and 2 columns)
GridPane grid;
#Override
public void start(Stage primaryStage) {
// instantiate labels and their properties
titleLabel = new Label("Tip Calculator");
titleLabel.setMaxWidth(Double.MAX_VALUE);
titleLabel.setAlignment(Pos.CENTER);
checkAmtLabel = new Label("Check Amount");
checkAmtLabel.setMaxWidth(Double.MAX_VALUE);
checkAmtLabel.setAlignment(Pos.CENTER_RIGHT);
tipPercentLabel = new Label("Tip Percent: 15%");
tipPercentLabel.setMaxWidth(Double.MAX_VALUE);
tipPercentLabel.setAlignment(Pos.CENTER_RIGHT);
splitLabel = new Label("Split");
splitLabel.setMaxWidth(Double.MAX_VALUE);
splitLabel.setAlignment(Pos.CENTER_RIGHT);
tipAmtLabel = new Label("Tip Amount");
tipAmtLabel.setMaxWidth(Double.MAX_VALUE);
tipAmtLabel.setAlignment(Pos.CENTER_RIGHT);
totalLabel = new Label("Total");
totalLabel.setMaxWidth(Double.MAX_VALUE);
totalLabel.setAlignment(Pos.CENTER_RIGHT);
amtPerPersonLabel = new Label("Amount per Person");
amtPerPersonLabel.setMaxWidth(Double.MAX_VALUE);
amtPerPersonLabel.setAlignment(Pos.CENTER_RIGHT);
// instantiate text fileds and their properties
double textFieldWidth = 100;
checkAmtText = new TextField();
checkAmtText.setOnMouseClicked(e -> ResetFields());
checkAmtText.setPrefWidth(textFieldWidth);
checkAmtText.setAlignment(Pos.CENTER_RIGHT);
tipAmtText = new TextField();
tipAmtText.setFocusTraversable(false);
tipAmtText.setPrefWidth(textFieldWidth);
tipAmtText.setAlignment(Pos.CENTER_RIGHT);
tipAmtText.setEditable(false);
totalText = new TextField();
totalText.setFocusTraversable(false);
totalText.setPrefWidth(textFieldWidth);
totalText.setAlignment(Pos.CENTER_RIGHT);
totalText.setEditable(false);
amtPerPersonText = new TextField();
amtPerPersonText.setFocusTraversable(false);
amtPerPersonText.setPrefWidth(textFieldWidth);
amtPerPersonText.setAlignment(Pos.CENTER_RIGHT);
amtPerPersonText.setEditable(false);
// instantiate a slider and its properties
tipPercentSlider = new Slider();
tipPercentSlider.setPrefWidth(10);
tipPercentSlider = new javafx.scene.control.Slider();
tipPercentSlider.setPrefWidth(150);
tipPercentSlider.setMin(0);
tipPercentSlider.setMax(25);
tipPercentSlider.setMajorTickUnit(5);
tipPercentSlider.setMinorTickCount(1);
tipPercentSlider.setBlockIncrement(1);
tipPercentSlider.setShowTickLabels(true);
tipPercentSlider.setShowTickMarks(true);
tipPercentSlider.setSnapToTicks(true);
tipPercentSlider.setValue(15);
tipPercentSlider.setOrientation(Orientation.HORIZONTAL);
tipPercentSlider.valueProperty().addListener(
(observable, oldvalue, newvalue) ->
{
tipPercentLabel.setText(String.format("Tip Percent:
%2d%s",newvalue.intValue(),"%"));
} );
// instantiate a choice box and its properties
splitChoiceBox = new ChoiceBox();
splitChoiceBox.getItems().addAll("1 Way", "2 Ways", "3 Ways", "4
Ways", "5 Ways");
splitChoiceBox.setValue("1 Way");
splitChoiceBox.setPrefWidth(150);
// instantiate a button and its properties
calcTipButton = new Button("Calculate Tip");
calcTipButton.setMaxWidth(Double.MAX_VALUE);
calcTipButton.setOnAction(e -> CalcButtonClick()) ;
// instantiate a grid pane and its properties
grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(10));
grid.add(titleLabel, 0, 0, 2, 1);
grid.addRow(1, checkAmtLabel, checkAmtText);
grid.addRow(2, tipPercentLabel, tipPercentSlider);
grid.addRow(3, splitLabel, splitChoiceBox);
grid.add(calcTipButton, 0, 4, 2, 1);
grid.addRow(5, tipAmtLabel, tipAmtText);
grid.addRow(6, totalLabel, totalText);
grid.addRow(7, amtPerPersonLabel, amtPerPersonText);
// instantiate the grid pane and put items in in grid
Scene scene = new Scene(grid);
scene.getRoot().setStyle("-fx-font: 20 'Comic Sans MS'");
primaryStage.setTitle("Tip Calculator");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
private void CalcButtonClick() {
/*
Get the check amount from checkAmtText
Get the tip percent from the slider
Get the split the choice box
Tip amount = check amount * tip percent
Total amount = check amount + tip amount
Amount per person = total amount / split
Print the tip amount in tipAmtText
Print the total amount in total Text
Print the split amtPerPerson Text
*/
double tipAmnt, checkAmnt, tipPercent,
totalAmnt, AmntPerPerson;
tipAmnt = Double.parseDouble(tipAmtText.getText());
AmntPerPerson =
Double.parseDouble(amtPerPersonText.getText());
checkAmnt = Double.parseDouble(checkAmtText.getText());
totalAmnt = Double.parseDouble(totalText.getText());
tipPercent = Double.parseDouble(tipPercentLabel.getText());
tipAmnt = checkAmnt * tipPercent;
totalAmnt = checkAmnt + tipAmnt;
tipAmtText.setText(currency.format(tipAmnt));
totalText.setText(currency.format(totalAmnt));
}
private void ResetFields() {
/*
Clear the check amount
Clear the tip amount
Clear the total amount
Clear the amount per person
Set the tip percent slider to 15%
Set the split choice box to “1 Way”
*/
}
}
You should use eventListener or FXML. Second, I think, would be easier. Need example?
UPDATE: (I added an example)
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation((getClass().getResource("Sample.fxml")));
Parent panel = fxmlLoader.load();
Scene scene = new Scene(panel, 300, 150);
primaryStage.setTitle("Sum of two numbers");
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Sample.fxml
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="150.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<children>
<AnchorPane prefHeight="55.0" prefWidth="300.0">
<children>
<HBox prefHeight="25.0" prefWidth="200.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0">
<children>
<Label text="x">
<HBox.margin>
<Insets left="31.0" />
</HBox.margin>
</Label>
<Label text="y">
<HBox.margin>
<Insets left="62.0" />
</HBox.margin>
</Label>
<Label text="z">
<HBox.margin>
<Insets left="62.0" />
</HBox.margin>
</Label>
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="20.0">
<children>
<TextField fx:id="xTextField" />
<TextField fx:id="yTextField" />
<TextField fx:id="zTextField" />
</children>
</HBox>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<HBox AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="20.0">
<children>
<Button mnemonicParsing="false" onAction="#sumIt" text="Sum it!" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="20.0" />
</children>
<children>
<Button mnemonicParsing="false" onAction="#clearAll" text="Clear all!" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="20.0" />
</children>
</HBox>
</AnchorPane>
</children>
</VBox>
SampleController.java
package application;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
public class SampleController {
#FXML
TextField xTextField, yTextField, zTextField;
public void sumIt() {
int sum;
sum = Integer.parseInt(xTextField.getText()) + Integer.parseInt(yTextField.getText());
zTextField.setText(Integer.toString(sum));
}
public void clearAll() {
xTextField.setText("");
yTextField.setText("");
zTextField.setText("");
}
}

How to achieve soft round effect on border in JavaFX

I have a generic border of a node and i want to make the border look like this image (both CSS and code way) in JavaFX:
Can anybody help me?
Thanks in advance
You should use box-shadow to add a soft round effect with border and border-radius.
border: 1px solid #888888;
box-shadow: 1px 1px 2px #888888;
border-radius: 25px;
The main Class for stage
public class SpiderMan extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws IOException {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"SpiderMan.fxml"
)
);
loader.setController(new clipRound());
Pane batman = loader.load();
stage.setTitle("Where's Spider man Round image?");
stage.setScene(new Scene(batman));
stage.show();
}
}
The Round Image Class View
class clipRound {
#FXML
private ImageView imageView;
#FXML
public void initialize() {
// set a clip to apply rounded border to the original image.
Rectangle clip = new Rectangle(
imageView.getFitWidth(), imageView.getFitHeight()
);
clip.setArcWidth(20); the radius Arch
clip.setArcHeight(20); the radius Arch
imageView.setClip(clip);
// snapshot the rounded image.
SnapshotParameters parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);
WritableImage image = imageView.snapshot(parameters, null);
// remove the rounding clip so that our effect can show through.
imageView.setClip(null);
// apply a shadow effect.
imageView.setEffect(new DropShadow(20, Color.BLACK));
// store the rounded image in the imageView.
imageView.setImage(image);
}
}
The round Image FXML view "SpiderMan.fxml"
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="313.0" prefWidth="477.0" style="-fx-background-color: azure;" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
<children>
<ImageView fx:id="imageView" layoutX="29.0" layoutY="44.0" fitHeight="224.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="http://collider.com/wp-content/uploads/lego-batman-movie-dc-super-heroes-unite-1.jpg" />
</image>
</ImageView>
</children>
</AnchorPane>
Snapshot :
snapshot programme is running

JavaFX How to change color of dialog/window title?

since yesterday, i'm trying to change the color of my dialog title (or maybe all title colors of my application) to get a black or dark color, because it's white color and not readable with grey background.
I still think it should work with css but i can't really find the specific entry for the title color.
I tried something like this in dialog.css but did not work, so commented out:
/*
.root {
-fx-text-base-color: blue;
-fx-text-background-color: green;
-fx-text-inner-color: red;
-fx-selection-bar-text: yellow;
}
*/
Here my Dialog class:
package de.test.dialog;
import java.io.IOException;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class Dialog extends Stage {
public static final String OK_DIALOG = "OK";
private final String OK_XML = "/fxml/dialog_ok.fxml";
public enum DIALOG_ACTION {
BUTTON_1, BUTTON_2, BUTTON_3, NOTHING, CLOSE_WINDOW
}
private DialogController controller = null;
private String message = null;
public Dialog(String name, String ... buttonName) {
String resource = getFXMLResource(name);
if (resource != null) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(resource));
Parent root = (Parent) fxmlLoader.load();
controller = fxmlLoader.getController();
controller.setButtons(buttonName);
setScene(new Scene(root));
}
catch (IOException e) {
e.printStackTrace();
}
}
setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
System.out.println("Closing?");
}
});
}
private String getFXMLResource(String name) {
String fxmlResource = null;
switch(name) {
case OK_DIALOG:
fxmlResource = OK_XML;
break;
default:
break;
}
return fxmlResource;
}
public Dialog.DIALOG_ACTION getAction() {
if (controller != null) {
return controller.getAction();
}
else {
return DIALOG_ACTION.NOTHING;
}
}
public void setMessage(String sMessage) {
this.message = sMessage;
if (controller != null) {
controller.setMessage(message);
}
}
public void setIcon(Image image) {
if (controller != null) {
controller.setIcon(image);
}
}
}
Dialog fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="176.0" prefWidth="400.0" stylesheets="#styles/dialog.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.test.dialog.DialogController">
<children>
<ImageView fx:id="imgIcon" fitHeight="48.0" fitWidth="48.0" layoutX="8.0" layoutY="25.0" pickOnBounds="true" preserveRatio="true" AnchorPane.leftAnchor="15.0" AnchorPane.topAnchor="25.0">
<image>
<Image url="#../icons/dialog/48a.png" />
</image>
</ImageView>
<Text fx:id="txtMessage" layoutX="85.0" layoutY="45.0" strokeType="OUTSIDE" strokeWidth="0.0" text="TEST" wrappingWidth="300.00" AnchorPane.leftAnchor="94.0" AnchorPane.rightAnchor="15.0" AnchorPane.topAnchor="25.0">
<font>
<Font size="14.0" />
</font>
</Text>
<Button fx:id="btn1" defaultButton="true" layoutX="295.0" layoutY="134.0" mnemonicParsing="false" onAction="#doAction" prefHeight="25.0" prefWidth="90.0" text="OK" AnchorPane.rightAnchor="15.0">
<font>
<Font size="14.0" />
</font>
</Button>
<Button fx:id="btn2" cancelButton="true" layoutX="180.0" layoutY="134.0" mnemonicParsing="false" onAction="#doAction" prefHeight="25.0" prefWidth="90.0" text="Abbrechen" visible="false" AnchorPane.rightAnchor="120.0">
<font>
<Font size="14.0" />
</font>
</Button>
<Button fx:id="btn3" layoutX="102.0" layoutY="134.0" mnemonicParsing="false" onAction="#doAction" prefHeight="25.0" prefWidth="90.0" text="Button 3" visible="false" AnchorPane.rightAnchor="225.0">
<font>
<Font size="14.0" />
</font>
</Button>
</children>
</AnchorPane>
Calling my dialog:
Dialog dialog = new Dialog(Dialog.OK_DIALOG, "Löschen", "Abbrechen");
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(((Node)e.getSource()).getScene().getWindow());
dialog.setResizable(false);
dialog.setTitle("Dateianhang löschen");
dialog.setMessage("Wollen Sie die ausgewählte(n) Datei(en) wirklich löschen?");
// Get the Stage.
//Stage stage = (Stage) dialog.getScene().getWindow();
// Add a custom icon.
//stage.getIcons().add(new Image("/icons/dialog/48a.png"));
dialog.showAndWait();
As you can see, i tried to change the title icon (commented out), and that worked. But no chance to change the color of the title.
If i try google whith e.g. javafx, i can see a lot of images with black title colors. So it must be possible to change the color, but i don't know how.
Any suggestions?
Greetings,
Tom
I stand to be corrected but I don't think you can set the color of the NATIVE title bar. I think what you are seeing in the google results are custom (user) made title bars.
Maybe this link is useful to you: https://arnaudnouard.wordpress.com/2013/02/02/undecorator-add-a-better-look-to-your-javafx-stages-part-i/
You can also have a look at the FXControls Dialogs source code and see how they have done it: http://fxexperience.com/controlsfx/features/dialogs/

Failed to load skin : null when applying css to fxml in Scene builder

I am trying to create a knob control for JavaFX with this example as starting point: http://fxexperience.com/2012/01/fun-javafx-2-0-audio-player/
In that example they are applying a skin (KnobSkin.java) to a slider in the css file.
I have created a custom control like this:
Knob.fxml
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<fx:root type="javafx.scene.layout.AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
<children>
<AnchorPane id="myTestButton" layoutX="0.0" layoutY="5.0" minHeight="49.0" prefHeight="140.0" prefWidth="14.0">
<children>
<Slider id="volume" orientation="VERTICAL" styleClass="knobStyle" />
</children>
</AnchorPane>
</children>
</fx:root>
Knob.java
package application;
public class Knob extends AnchorPane {
#FXML
private AnchorPane myTestButton;
public Knob() {
FXMLLoader fxmlLoader = new FXMLLoader(
getClass().getResource("/application/Knob.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
My main scene looks like this:
test.fxml
<?import application.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?scenebuilder-classpath-element ../../bin?>
<AnchorPane prefHeight="217.0" prefWidth="221.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
<Knob layoutX="5.0" layoutY="4.0" />
</AnchorPane>
When I try to open the test.fxml file in Scene Builder and apply this css to it:
.slider.knobStyle {
-fx-skin: "application.KnobSkin";
}
I get the following error:
Failed to load skin 'StringProperty [bean: Slider[id=volume, styleClass=slider knobStyle], name:skinClassName, value:application.KnobSkin]' for control Slider[id=volume, styleClass=slider knobStyle] :null
If I run the application the knob is displayed perfectly.
Any idea what I have done wrong?
Thanks!
After reading this blog post: http://www.guigarage.com/2012/11/custom-ui-controls-with-javafx-part-1/
I found that if I change my class Knob.java to
package application;
public class Knob extends AnchorPane {
#FXML
private AnchorPane myTestButton;
public Knob() {
setSkinClassName(KnobSkin.class.getName());
}
}
And I remove the Knob.fxml the knob will show up in Scene Builder when I select my stylesheet

Resources