The button freezes - button

I'm currently being asked to design a robot and give it a few capabilities by the technical college. One of these capabilities is that on a click on the Revive button, the robot will appear again (after having disappeared by right-clicking the robot itself three times!).
My code doesn't work though. On a click on the button it seems frozen and does not react anymore!
How can I fix this?
Here my code:
package at.ac.fhcampuswien;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class HelloRobot extends Application {
private int counter = 0;
private static final int BOARD_SIZE = 600;
#Override
public void start(Stage primaryStage) throws Exception{
Group root = new Group();
Group robot = FXMLLoader.load(getClass().getResource("robot.fxml"));
root.getChildren().add(robot);
Label label = new Label("");
label.setPrefWidth(BOARD_SIZE);
label.setAlignment(Pos.CENTER);
root.getChildren().addAll(label);
Button revive = new Button("Revive!");
revive.setOnAction(actionEvent -> {
if(counter < 3) {
label.setText("!Dead yet!?");
} else {
root.getChildren().add(robot);
label.setText("Be nice this time");
counter = 0;
}
/*
for(Node node: root.getChildren()){
if(robot != null)
{
label.setText("!Dead yet!?");
}
}
if(counter == 3) {
root.getChildren().add(robot);
label.setText("Be nice this time");
counter = 0;
}*/
});
root.getChildren().add(revive);
robot.setOnMousePressed(mouseEvent -> {
if (mouseEvent.isSecondaryButtonDown()) {
if(counter == 0) {
label.setText("Oooooouch!");
counter++;
}
else if(counter == 1){
label.setText("Please no!");
counter++;
}
else if(counter == 2){
root.getChildren().remove(robot);
counter++;
}
}
});
Scene scene = new Scene(root, BOARD_SIZE, BOARD_SIZE);
primaryStage.setTitle("Hello Robot");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is the robot.fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.CubicCurve?>
<?import javafx.scene.shape.Ellipse?>
<?import javafx.scene.shape.Polygon?>
<?import javafx.scene.shape.Rectangle?>
<Group fx:id="robot" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="at.ac.fhcampuswien.RobotController">
<children>
<AnchorPane prefHeight="600.0" prefWidth="600.0">
<children>
<Polygon fill="#ff1f1f" layoutX="349.0" layoutY="425.0" points="-18.0, 47.0, 51.0, 47.0, 0.0, -60.0" stroke="BLACK" strokeType="INSIDE" />
<Polygon fill="#ff1f1f" layoutX="247.0" layoutY="433.0" points="-47.0, 40.0, 25.0, 40.0, 8.0, -70.0" stroke="BLACK" strokeType="INSIDE" />
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="200.0" layoutX="200.0" layoutY="163.0" stroke="BLACK" strokeType="INSIDE" width="200.0" />
<Circle fill="#eaff1f" layoutX="300.0" layoutY="163.0" radius="100.0" stroke="BLACK" strokeType="INSIDE" />
<Ellipse fill="#1eff3e" layoutX="264.0" layoutY="117.0" radiusX="36.0" radiusY="14.0" stroke="BLACK" strokeType="INSIDE" />
<Ellipse fill="#1eff3e" layoutX="336.0" layoutY="117.0" radiusX="36.0" radiusY="14.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fill="DODGERBLUE" layoutX="300.0" layoutY="163.0" radius="22.0" stroke="BLACK" strokeType="INSIDE" />
<CubicCurve controlX1="-57.0" controlX2="56.0" controlY1="41.0" controlY2="41.0" endX="56.0" fill="DODGERBLUE" layoutX="301.0" layoutY="203.0" startX="-57.0" stroke="BLACK" />
<Polygon fill="DODGERBLUE" layoutX="170.0" layoutY="262.0" points="30.0, 30.0, 30.0, -34.0, -43.0, 0.0" stroke="BLACK" strokeType="INSIDE" />
<Polygon fill="DODGERBLUE" layoutX="370.0" layoutY="265.0" points="30.0, 30.0, 30.0, -34.0, 103.0, -4.0" stroke="BLACK" strokeType="INSIDE" />
</children>
</AnchorPane>
</children>
</Group>

Related

JavaFX FXML file not opening error chosen file should be valid FXML but it is working for other FXML files

I am working on image editor using JavaFX FXML ,scene builder 2.0 .I am getting this error continuously where my scene builder doesn't read FXML file when double clicking on it. I haven't used an other other libraries or anything and have tried opening particular FXML from scene builder directly as well.
I have tried using possible solutions on this question but non seems to work for me.
enter image description here
package imageeditor;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javax.imageio.ImageIO;
import imageeditor.CommandCenter;
import javafx.scene.control.ColorPicker;
public class FXMLDocumentController implements Initializable {
// #FXML
// private Edit Images = new Edit();
// #FXML
// private ImageView ImageView,i ;
// #FXML private ImageView mImageView;
#FXML
private AnchorPane mAnchorPane;
#FXML
private ImageView mImageView;
#FXML
private Button btnUndo;
#FXML
private Button btnRedo;
#FXML
private Button exit;
#FXML
private Button reset;
#FXML
private Button uploadbtn,savebtn;
#FXML
private Label l1,l2,l3,l4,l5,l6,l7;
#FXML
private Slider bright;
#FXML
private Slider gauss;
#FXML
private Slider hue;
#FXML
private Slider saturation;
#FXML
private Slider contrast;
#FXML
private Button cropbtn ;
#FXML
private Button stickersbtn ;
#FXML
private Button textbtn ;
// #FXML
// private Button ;
#FXML
private ColorPicker framecolour ;
private ColorAdjust AdjustEffect = new ColorAdjust();
// CommandCenter CommandCenter= new CommandCenter();
#FXML
private void LoadImage(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
File file = fileChooser.showOpenDialog(null);
try
{
BufferedImage bufferedImage = ImageIO.read(file);
Image image = SwingFXUtils.toFXImage(bufferedImage, null);
mImageView.setImage(image);
Image currentImage = getSnapshot();
CommandCenter.getInstance().setImageAndView(currentImage);
CommandCenter.getInstance().setOriginalImage(currentImage);
// CommandCenter.getInstance().setImageView(mImageView);
// CommandCenter.getInstance().setOriginalImage(image);
} catch (IOException ex) {
}
}
#FXML
private void SaveImage(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save Image");
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
File file = fileChooser.showSaveDialog(null);
if (file != null) {
try {
BufferedImage bImage = SwingFXUtils.fromFXImage(mImageView.snapshot(null, null), null);
ImageIO.write(bImage,"png", file);
} catch (IOException ex) {
}
}
}
//#FXML void quit(ActionEvent event) {
// System.exit(0);
// }
#FXML void undo(ActionEvent event) {
undo();
}
#FXML void redo(ActionEvent event) {
redo();
}
// save image as snapshot
private Image getSnapshot() {
SnapshotParameters snapshotParameters = new SnapshotParameters();
snapshotParameters.setViewport(mImageView.getViewport());
// snapshotParameters.setViewport(new Rectangle2D(mImageView.getX(), mImageView.getY(), mImageView.getImage().getWidth(), mImageView.getImage().getHeight()));
return mAnchorPane.snapshot(snapshotParameters, null);
}
private void undo() {
if (CommandCenter.getInstance().hasUndoImage()) {
Image currentImage = getSnapshot();
CommandCenter.getInstance().addRedoImage(currentImage);
Image undoImage = CommandCenter.getInstance().getUndoImage();
resetEffectsSliders();
CommandCenter.getInstance().setImageAndView(undoImage);
mImageView.setImage(undoImage);
enableRedo();
if (!CommandCenter.getInstance().hasUndoImage()) {
disableUndo();
}
}
}
// redo action
private void redo() {
System.out.println("redo image added");
if (CommandCenter.getInstance().hasRedoImage()) {
Image currentImage = getSnapshot();
CommandCenter.getInstance().addUndoImage(currentImage);
Image redoImage = CommandCenter.getInstance().getRedoImage();
resetEffectsSliders();
CommandCenter.getInstance().setImageAndView(redoImage);
mImageView.setImage(redoImage);
enableUndo();
if (!CommandCenter.getInstance().hasRedoImage()) {
disableRedo();
}
}
}
// update the image and associated properties
private void updateImageAndProperties() {
CommandCenter.getInstance().storeLastImageAsUndo();
CommandCenter.getInstance().clearRedoImages(); // new "path" so clear redo images
disableRedo();
enableUndo();
Image currentImage = getSnapshot();
CommandCenter.getInstance().setImageAndView(currentImage);
resetEffectsSliders();
mImageView.setImage(currentImage);
}
// start over with original image
private void startOver() {
resetEffectsSliders();
Image originalImage = CommandCenter.getInstance().getOriginalImage();
CommandCenter.getInstance().setImageAndView(originalImage);
mImageView.setImage(originalImage);
CommandCenter.getInstance().clearRedoImages();
CommandCenter.getInstance().clearUndoImages();
disableUndo();
disableRedo();
}
private void resetEffectsSliders() {
bright.setValue(0);
contrast.setValue(0.0);
hue.setValue(0.0);
saturation.setValue(0.0);
}
// enable undo buttons
private void enableUndo() {
btnUndo.setDisable(false);
}
// disable undo buttons
private void disableUndo() {
btnUndo.setDisable(true);
}
// enable redo buttons
private void enableRedo() {
btnRedo.setDisable(false);
}
// disable redo buttons
private void disableRedo() {
btnRedo.setDisable(true);
}
// enable start over buttons
private void enableStartOver() {
reset.setDisable(false);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
CommandCenter.getInstance().setImageView(mImageView);
// Images.GaussSliderEvent(gauss);
// Images.BrightSliderEvent(bright);
// Images.SaturationSliderEvent(saturation);
// Images.HueSliderEvent(hue);
// Images.ContrastSliderEvent(contrast);
mImageView.setEffect(AdjustEffect);
// take a snapshot to set as initial image
Image initialImage = getSnapshot();
mImageView.setImage(initialImage);
CommandCenter.getInstance().setImageView(mImageView);
CommandCenter.getInstance().setOriginalImage(initialImage);
CommandCenter.getInstance().setImageAndView(initialImage);
// brightness slider
bright.valueProperty().addListener((observable, oldValue, newValue) -> {
AdjustEffect.setBrightness(newValue.doubleValue());
mImageView.setEffect(AdjustEffect);
updateImageAndProperties();
});
// hue slider
hue.valueProperty().addListener((observable, oldValue, newValue) -> {
AdjustEffect.setHue(newValue.doubleValue());
mImageView.setEffect(AdjustEffect);
updateImageAndProperties();
});
// saturation slider
saturation.valueProperty().addListener((observable, oldValue, newValue) -> {
AdjustEffect.setSaturation(newValue.doubleValue());
//Image.setEffect(AdjustEffect);
updateImageAndProperties();
});
// contrast slider
contrast.valueProperty().addListener((observable, oldValue, newValue) -> {
AdjustEffect.setContrast(newValue.doubleValue());
// Image.setEffect(AdjustEffect);
updateImageAndProperties();
});
// gauss slider
gauss.valueProperty().addListener((observable, oldValue, newValue) -> {
// gauss.setRadius(newValue.doubleValue()*100);
// Image.setEffect(gauss);
updateImageAndProperties();
});
}
}
Java FXML file is
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="650.0" prefWidth="1150.0" style="-fx-background-color: #FFFFF0;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="imageeditor.FXMLDocumentController">
<children>
<Button fx:id="uploadbtn" layoutX="797.0" layoutY="24.0" onAction="#LoadImage" opacity="0.75" style="-fx-background-color: #800000;" text="UPLOAD IMAGE" textFill="WHITE">
<font>
<Font name="Bell MT Bold" size="18.0" />
</font></Button>
<ImageView fx:id="ImageView" fitHeight="639.0" fitWidth="927.0" layoutX="201.0" layoutY="94.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#BG.jpg" />
</image></ImageView>
<Button fx:id="savebtn" layoutX="1007.0" layoutY="23.0" mnemonicParsing="false" onAction="#SaveImage" opacity="0.75" prefHeight="34.0" prefWidth="105.0" style="-fx-background-color: #800000;" text="SAVE" textFill="WHITE">
<font>
<Font name="Bell MT Bold" size="18.0" />
</font></Button>
<Button fx:id="resetbtn" layoutX="54.0" layoutY="576.0" text="RESET" />
<Button fx:id="undobtn" layoutX="25.0" layoutY="94.0" mnemonicParsing="false" style="-fx-background-color: #800000;" text="UNDO" textFill="WHITE" />
<Button fx:id="redobtn" layoutX="115.0" layoutY="94.0" mnemonicParsing="false" style="-fx-background-color: #800000;" textFill="WHITE"text="REDO" />
<Button fx:id="cropbtn" layoutX="63.0" layoutY="143.0" mnemonicParsing="false" text="CROP" />
<ColorPicker fx:id="framecolour" layoutX="52.0" layoutY="414.0" />
<Button fx:id="stickersbtn" layoutX="24.0" layoutY="516.0" mnemonicParsing="false" text="ADD STICKERS" />
<Button fx:id="textbtn" layoutX="44.0" layoutY="470.0" mnemonicParsing="false" text="ADD TEXT" />
<Slider fx:id="gauss" blockIncrement="0.1" layoutX="42.0" layoutY="315.0" max="1.0" min="0" />
<Slider fx:id="contrast" blockIncrement="0.01" layoutX="42.0" layoutY="237.0" max="1.0" min="-1.0" />
<Slider fx:id="hue" blockIncrement="0.01" layoutX="42.0" layoutY="199.0" max="1.0" min="-1.0" />
<Slider fx:id="saturation" blockIncrement="0.01" layoutX="42.0" layoutY="277.0" max="1.0" min="-1.0" />
<Slider fx:id="bright" blockIncrement="0.01" layoutX="38.0" layoutY="355.0" max="1.0" min="-1.0" />
<Slider fx:id="frame" blockIncrement="0.01" layoutX="42.0" layoutY="393.0" max="1.0" min="-1.0" />
<ImageView fitHeight="63.0" fitWidth="91.0" layoutX="31.0" layoutY="13.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#logo.png" />
</image>
</ImageView>
<Label fx:id="l1" layoutX="140.0" layoutY="18.0" prefHeight="51.0" prefWidth="451.0" text="IMAGE EDITOR AND ENHANCER" textFill="#830c0c">
<font>
<Font name="Artifakt Element Black Italic" size="29.0" />
</font>
</Label>
<Label fx:id="l2" layoutX="81.0" layoutY="182.0" text="hue" />
<Label fx:id="l3" layoutX="76.0" layoutY="220.0" text="contrast" />
<Label fx:id="l4" layoutX="68.0" layoutY="258.0" text="saturation" />
<Label fx:id="l5" layoutX="76.0" layoutY="298.0" text="gauss" />
<Label fx:id="l6" layoutX="74.0" layoutY="331.0" text="brightness" />
<Label fx:id="l7" layoutX="74.0" layoutY="376.0" text="frame" />
</children>
</AnchorPane>
SceneBuilder bring a stacktrace if you press show details button
Details :
java.io.IOException: org.xml.sax.SAXParseException; lineNumber: 28; columnNumber: 149; Element type "Button" must be followed by either attribute specifications, ">" or "/>".
at com.oracle.javafx.scenebuilder.kit.fxom.glue.GlueLoader.load(GlueLoader.java:93)
at com.oracle.javafx.scenebuilder.kit.fxom.glue.GlueLoader.load(GlueLoader.java:76)
at com.oracle.javafx.scenebuilder.kit.fxom.glue.GlueDocument.<init>(GlueDocument.java:54)
at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.<init>(FXOMDocument.java:84)
at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.<init>(FXOMDocument.java:108)
at com.oracle.javafx.scenebuilder.kit.editor.EditorController.updateFxomDocument(EditorController.java:2560)
at com.oracle.javafx.scenebuilder.kit.editor.EditorController.setFxmlTextAndLocation(EditorController.java:763)
at com.oracle.javafx.scenebuilder.app.DocumentWindowController.loadFromFile(DocumentWindowController.java:389)
at com.oracle.javafx.scenebuilder.app.SceneBuilderApp.performOpenFiles(SceneBuilderApp.java:668)
at com.oracle.javafx.scenebuilder.app.SceneBuilderApp$1.invalidated(SceneBuilderApp.java:520)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(Unknown Source)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
at javafx.base/javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(Unknown Source)
at javafx.base/javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(Unknown Source)
at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(Unknown Source)
at javafx.base/javafx.beans.property.BooleanPropertyBase.set(Unknown Source)
at com.oracle.javafx.scenebuilder.kit.library.user.UserLibrary.lambda$updateFirstExplorationCompleted$7(UserLibrary.java:371)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(Unknown Source)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.xml.sax.SAXParseException; lineNumber: 28; columnNumber: 149; Element type "Button" must be followed by either attribute specifications, ">" or "/>".
at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.seekCloseOfStartTag(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.oracle.javafx.scenebuilder.kit.fxom.glue.GlueLoader.load(GlueLoader.java:91)
... 23 more
java.io.IOException: org.xml.sax.SAXParseException; lineNumber: 28; columnNumber: 149;
Line 28:
<Button fx:id="redobtn" layoutX="115.0" layoutY="94.0" mnemonicParsing="false" style="-fx-background-color: #800000;" textFill="WHITE"text="REDO" />
Error: there is no space in between textFill and text attributes , so Compiler can't read properly button tag
fix line 28 :
<Button fx:id="redobtn" layoutX="115.0" layoutY="94.0" mnemonicParsing="false" style="-fx-background-color: #800000;" textFill="WHITE" text="REDO" />
Now scenebuilder can open that file

JavaFX Slider with 2 different colors , for example green for selected area and red for unselected area

What i want to achieve is the have a JavaFX Slider like the below :
I want the selected are to be green and the unselected area to be red :
Can this be done with let's say simple css because JavaFX is awesome i am sure it can but now how :_)
What i was doing till ....
Until now i was just adding a StackPane and behind that a ProgressBar , synchronized with the value of the Slider , what i mean? :)
, but hey now i need two colors and i have to create two ProgressBars in a StackPane with different colors (RED and Green) .... to much code ...
1 slider and 2 progress bars , I will post below the .fxml code , .java code and the needed .css for look and feel :)
Any question feel free to answer :)
As for the code , this is created for XR3Player (Open Source Github Project)
.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<fx:root prefHeight="389.0" prefWidth="228.0" style="-fx-background-color: #202020;" stylesheets="#../../style/application.css" type="StackPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/9.0.1">
<children>
<BorderPane fx:id="borderPane" minHeight="0.0" minWidth="0.0">
<bottom>
<StackPane minHeight="0.0" minWidth="0.0" BorderPane.alignment="CENTER">
<children>
<HBox alignment="CENTER" maxHeight="-Infinity" minHeight="0.0" minWidth="0.0" prefHeight="15.0">
<children>
<ProgressBar fx:id="volumeProgress1" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" mouseTransparent="true" prefHeight="15.0" progress="1.0" HBox.hgrow="ALWAYS">
<styleClass>
<String fx:value="transparent-progress-bar" />
<String fx:value="transparent-volume-progress-bar2-nostrip" />
</styleClass>
</ProgressBar>
<ProgressBar fx:id="volumeProgress2" layoutX="10.0" layoutY="10.0" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" mouseTransparent="true" prefHeight="15.0" progress="1.0" HBox.hgrow="ALWAYS">
<styleClass>
<String fx:value="transparent-progress-bar" />
<String fx:value="transparent-volume-progress-bar3-nostrip" />
</styleClass>
</ProgressBar>
</children>
</HBox>
<Slider fx:id="masterVolumeSlider" majorTickUnit="15.0" max="150.0" maxWidth="1.7976931348623157E308" minorTickCount="55" value="75.0">
<styleClass>
<String fx:value="transparency-slider" />
<String fx:value="timer-slider" />
</styleClass>
</Slider>
</children>
<BorderPane.margin>
<Insets left="5.0" right="5.0" />
</BorderPane.margin>
</StackPane>
</bottom>
</BorderPane>
</children>
</fx:root>
.java
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import main.java.com.goxr3plus.xr3player.application.tools.InfoTool;
public class MixTabInterface extends StackPane {
//--------------------------------------------------------------
#FXML
private BorderPane borderPane;
#FXML
private ProgressBar volumeProgress1;
#FXML
private ProgressBar volumeProgress2;
#FXML
private Slider masterVolumeSlider;
// -------------------------------------------------------------
/**
* Constructor.
*/
public MixTabInterface() {
// ------------------------------------FXMLLOADER ----------------------------------------
FXMLLoader loader = new FXMLLoader(getClass().getResource(InfoTool.PLAYERS_FXMLS + "MixTabInterface.fxml"));
loader.setController(this);
loader.setRoot(this);
try {
loader.load();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* Called as soon as fxml is initialized
*/
#FXML
private void initialize() {
//masterVolumeSlider
masterVolumeSlider.boundsInLocalProperty().addListener((observable , oldValue , newValue) -> calculateBars());
masterVolumeSlider.valueProperty().addListener((observable , oldValue , newValue) -> {
calculateBars();
});
}
/**
* Calculate bars positioning
*/
private void calculateBars() {
//Variables
double value = masterVolumeSlider.getValue();
double half = masterVolumeSlider.getMax() / 2;
double masterVolumeSliderWidth = masterVolumeSlider.getWidth();
//Progress Max1
volumeProgress1.setProgress(1);
volumeProgress2.setProgress(1);
//Below is mind tricks
if ((int) value == (int) half) {
volumeProgress1.setMinWidth(masterVolumeSliderWidth / 2);
volumeProgress2.setMinWidth(masterVolumeSliderWidth / 2);
} else if (value < half) {
double progress = 1.0 - ( value / half );
double minimumWidth = masterVolumeSlider.getWidth() / 2 + ( masterVolumeSlider.getWidth() / 2 ) * ( progress );
volumeProgress1.setMinWidth(masterVolumeSliderWidth - minimumWidth);
volumeProgress1.setMaxWidth(masterVolumeSliderWidth - minimumWidth);
volumeProgress2.setMinWidth(minimumWidth);
} else if (value > half) {
double progress = ( value - half ) / half;
double minimumWidth = masterVolumeSlider.getWidth() / 2 + ( masterVolumeSlider.getWidth() / 2 ) * ( progress );
volumeProgress1.setMinWidth(minimumWidth);
volumeProgress2.setMinWidth(masterVolumeSliderWidth - minimumWidth);
volumeProgress2.setMaxWidth(masterVolumeSliderWidth - minimumWidth);
}
}
/**
* #return the borderPane
*/
public BorderPane getBorderPane() {
return borderPane;
}
/**
* #return the masterVolumeSlider
*/
public Slider getMasterVolumeSlider() {
return masterVolumeSlider;
}
}
.css
.transparent-volume-progress-bar2-nostrip > .bar,.transparent-volume-progress-bar2-nostrip:indeterminate .bar,.transparent-volume-progress-bar2-nostrip:determinate .track,.transparent-volume-progress-bar2-nostrip:indeterminate .track{
-fx-accent:rgb(0.0, 144.0, 255.0);
-fx-background-color: -fx-accent;
-fx-background-radius:0.0;
-fx-border-radius:0.0;
}
.transparent-volume-progress-bar3-nostrip > .bar,.transparent-volume-progress-bar3-nostrip:indeterminate .bar,.transparent-volume-progress-bar3-nostrip:determinate .track,.transparent-volume-progress-bar3-nostrip:indeterminate .track{
-fx-accent:#fc4f4f;
-fx-background-color: -fx-accent;
-fx-background-radius:0.0;
-fx-border-radius:0.0;
}
.progress-bar > .bar {
-fx-accent:firebrick;
/*-fx-background-color:firebrick;*/
-fx-background-color: linear-gradient(
from 0.0px 0.75em to 0.75em 0.0px,
repeat,
-fx-accent 0.0%,
-fx-accent 49.0%,
derive(-fx-accent, 30.0%) 50.0%,
derive(-fx-accent, 30.0%) 99.0%
);
-fx-background-insets: 3.0;
-fx-padding: 0.2em;
}
.transparent-progress-bar:determinate .track,.transparent-progress-bar:indeterminate .track{
-fx-background-color:rgb(0.0,0.0,0.0,0.5);
}
/* .transparent-progress-bar */
.transparent-progress-bar > .bar,.transparent-progress-bar:indeterminate .bar{
-fx-accent:firebrick;
}

How can I click a GridPane Cell and have it perform an action?

I'm new to JavaFX (Java for that matter) and I want to be able to click a GridPane and have it display my room attributes in a side-panel(or to console at this point). I've managed to setup a mouse event but I don't think it's the right tool for the job. When I click anywhere in the grid, it returns "null" and won't give me the cell coordinates(maybe there's better or more useful info to gather here?).
I'm using Scene Builder as well.
Controller Class
import Data.Area;
import Model.Grid;
import Model.TileSet;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class Controller {
InputStream rinput = getClass().getResourceAsStream("/red.png");
Image red = new Image(rinput);
ImageView redimg = new ImageView(red);
InputStream binput = getClass().getResourceAsStream("/black.png");
Image black = new Image(binput);
InputStream pinput = getClass().getResourceAsStream("/pink.png");
Image pink = new Image(binput);
#FXML
public GridPane gridmane;
public void genSmall(ActionEvent actionEvent) throws IOException {
Grid grid = new Grid(new Area(40, 40));
grid.getPathfinder().shufflePartitions();
grid.getPathfinder().fillPartitions();
grid.getPathfinder().generateHallways();
grid.getPathfinder().placeWalls();
importGrid(gridmane, grid);
gridmane.getScene().getWindow().sizeToScene();
}
public void genMed(ActionEvent actionEvent) throws IOException {
Grid grid = new Grid(new Area(60, 60));
grid.getPathfinder().shufflePartitions();
grid.getPathfinder().fillPartitions();
grid.getPathfinder().generateHallways();
grid.getPathfinder().placeWalls();
gridmane.getScene().getWindow().sizeToScene();
gridmane.getScene().getWindow().setHeight(600);
gridmane.getScene().getWindow().setWidth(600);
importGrid(gridmane, grid);
}
public void genLarge(ActionEvent actionEvent) throws IOException {
Grid grid = new Grid(new Area(80, 80));
grid.getPathfinder().shufflePartitions();
grid.getPathfinder().fillPartitions();
grid.getPathfinder().generateHallways();
grid.getPathfinder().placeWalls();
gridmane.getScene().getWindow().sizeToScene();
gridmane.getScene().getWindow().setHeight(800);
gridmane.getScene().getWindow().setWidth(800);
importGrid(gridmane, grid);
}
private void importGrid(GridPane gridPane, Grid grid) {
gridPane.getChildren().clear(); // remove old children
for (int i = 0; i < grid.getSize().height; i++) {
for (int j = 0; j < grid.getSize().width; j++) {
if (grid.getContent()[j + (i * grid.getSize().width)] == TileSet.floorTile) {
changeSquare(gridPane, i, j, Color.WHITE, red);
}
else if (grid.getContent()[j + (i * grid.getSize().width)] == TileSet.wallTile) {
changeSquare(gridPane, i, j, Color.GRAY, black);
}
else {
changeSquare(gridPane, i, j, Color.BLACK, pink);
}
}
}
}
private void changeSquare(GridPane gridPane, int xCoordinate, int yCoordinate, Color color, Image image) {
Rectangle rect = new Rectangle();
ImageView fimage = new ImageView(image);
rect.setStroke(Color.BLACK);
rect.setFill(color);
rect.setWidth(10);
rect.setHeight(10);
gridPane.add(fimage, xCoordinate, yCoordinate);
}
public void clickGrid(javafx.scene.input.MouseEvent event) {
Node source = (Node)event.getSource() ;
Integer colIndex = gridmane.getColumnIndex(source);
Integer rowIndex = gridmane.getRowIndex(source);
System.out.println("Mouse clicked cell: " + colIndex + "And: " + rowIndex);
}
}
Main Class
public class Main extends Application {
Stage stage = new Stage();
int val = 40;
#Override
public void start(Stage primaryStage) throws Exception {
this.stage = primaryStage;
setVal(val);
}
public static void main(String[] args) {
launch(args);
}
public void setVal(int i) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("/view.fxml"));
stage.setTitle("Dungeon Generator");
stage.setScene(new Scene(root, 450, 450));
//primaryStage.setResizable(false);
stage.sizeToScene();
stage.show();
}
}
FXML File
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="332.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
<children>
<MenuBar>
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button alignment="CENTER" mnemonicParsing="false" onAction="#genSmall" prefHeight="27.0" prefWidth="64.0" text="Small" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets left="20.0" />
</HBox.margin>
</Button>
<Button alignment="CENTER" mnemonicParsing="false" onAction="#genMed" text="Medium" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets left="20.0" />
</HBox.margin>
</Button>
<Button alignment="CENTER" mnemonicParsing="false" onAction="#genLarge" prefHeight="27.0" prefWidth="66.0" text="Large" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets left="20.0" />
</HBox.margin>
</Button>
</children>
</HBox>
<StackPane>
<children>
<GridPane fx:id="gridmane" maxHeight="-Infinity" maxWidth="-Infinity" onMouseClicked="#clickGrid" VBox.vgrow="NEVER" />
</children>
</StackPane>
</children>
</VBox>
Since you register the event handler at the GridPane, the source of the event is the GridPane itself. You did not set the row/column index for the GridPane and it wouldn't contain any useful information.
In this case you need to get the node that was actually clicked from the MouseEvent:
public void clickGrid(javafx.scene.input.MouseEvent event) {
Node clickedNode = event.getPickResult().getIntersectedNode();
if (clickedNode != gridmane) {
// click on descendant node
Integer colIndex = GridPane.getColumnIndex(clickedNode);
Integer rowIndex = GridPane.getRowIndex(clickedNode);
System.out.println("Mouse clicked cell: " + colIndex + " And: " + rowIndex);
}
}
In this case the code works like this since the children of your GridPane don't have children of their own that could be the intersected node.
If you want to add children that could have children of their own you need to go up through the node hierarchy until you find a child of the GridPane:
if (clickedNode != gridmane) {
// click on descendant node
Node parent = clickedNode.getParent();
while (parent != gridmane) {
clickedNode = parent;
parent = clickedNode.getParent();
}
Integer colIndex = GridPane.getColumnIndex(clickedNode);
Integer rowIndex = GridPane.getRowIndex(clickedNode);
System.out.println("Mouse clicked cell: " + colIndex + " And: " + rowIndex);
}

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("");
}
}

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/

Resources