This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I've tried my hardest to get a button to change scenes but I can't get it to work.
I'm getting a nullpointerexception when I click on the button. It's something to do with the button2action method in the controller class. I know it's linked up correctly with the FXML because of the debug message I'm printing when it's clicked on.
I've spent many hours in vain trying to get this to work as you might be able to see from all the crap I've commented out in the main class (some of this might have worked with tweaks so I've left it in just in case someone can spot something I can't in that mess).
Here is my controller:
package com.frogger.mainapp;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Scene;
public class SampleController {
#FXML
public void button2action(ActionEvent event) {
System.out.println("This is horrible!");
Main.primaryStage.setScene(Main.scene);
Main.primaryStage.centerOnScreen();
Main.animal2 = new Animal("file:resources/froggerUp.png", 400.00, 700.00, true);
Main.background.add(Main.animal2);
}
}
Here is my FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="558.0" prefWidth="355.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.frogger.mainapp.SampleController">
<children>
<VBox alignment="CENTER" prefHeight="558.0" prefWidth="355.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<!-- fitHeight="183.0" fitWidth="355.0"-->
<ImageView pickOnBounds="true" preserveRatio="true" VBox.vgrow="ALWAYS">
<image>
<Image url="#Frogger_background_top.png" />
</image>
</ImageView>
<Button alignment="CENTER" mnemonicParsing="false" prefHeight="131.0" prefWidth="610.0" style="-fx-background-color: green;" text="Single Player Mode">
<font>
<Font name="Comic Sans MS Bold" size="28.0" />
</font>
</Button>
<Button fx:id="bt2" mnemonicParsing="false" onAction="#button2action" prefHeight="149.0" prefWidth="653.0" style="-fx-background-color: red;" text="Two Player Mode">
<font>
<Font name="Comic Sans MS Bold" size="28.0" />
</font>
</Button>
<Button mnemonicParsing="false" prefHeight="137.0" prefWidth="355.0" style="-fx-background-color: blue;" text="High Score">
<font>
<Font name="Comic Sans MS Bold" size="28.0" />
</font>
</Button>
</children>
</VBox>
</children>
</AnchorPane>
Here is my main class:
package com.frogger.mainapp;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class Main extends Application {
AnimationTimer timer;
public static MyStage background;
Animal animal;
public static Animal animal2;
public static Stage primaryStage;
public static Scene scene;
private boolean secondPlayer;
#FXML private Button bt2;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
background = new MyStage();
scene = new Scene(background,600,800);
// scene = new Scene(background,600,800);
//loginScene buttons
// Label label1= new Label("Welcome to my Frogger Game");
// Button button1= new Button("Single Player Mode");
// Button button2= new Button("Two Player Mode");
// bt2.addEventHandler(ActionEvent.ACTION, (e)->{
// animal2 = new Animal("file:resources/froggerUp.png", 400.00, 700.00, true);
// background.add(animal2);
// primaryStage.setScene(scene);
// primaryStage.centerOnScreen();
// });
//
// });
//Todo: Get the buttons working
//setting up loginScene
// VBox layout1 = new VBox(20);
// Image image = new Image("file:Frogger_background.png");
// ImageView iv1 = new ImageView();
// iv1.setImage(image);
// Image image = new Image("file:Frogger_background.png");
// BackgroundSize backgroundSize = new BackgroundSize(320, 480, true, true, true, false);
// BackgroundImage loginBack = new BackgroundImage(image, BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, backgroundSize);
// layout1.setBackground(new Background(loginBack));
// layout1.getChildren().addAll(label1, button1, button2);
Parent root = FXMLLoader.load(getClass().getResource("/Sample.fxml"));
Scene loginScene = new Scene(root,320, 480);
// button2action(primaryStage, scene);
// String css = Main.class.getResource("application.css").toExternalForm();
// loginScene.getStylesheets().add(css);
primaryStage.setResizable(false);
primaryStage.setScene(loginScene);
primaryStage.show();
// scene.getStylesheets().add(getClass().getResource("/application.css").toExternalForm());
MyBackgroundImage froggerback = new MyBackgroundImage("file:resources/iKogsKW.png");
background.add(froggerback);
background.add(new Log("file:resources/log3.png", 150, 0, 166, 0.75));
background.add(new Log("file:resources/log3.png", 150, 220, 166, 0.75));
background.add(new Log("file:resources/log3.png", 150, 440, 166, 0.75));
background.add(new Log("file:resources/logs.png", 300, 0, 276, -2));
background.add(new Log("file:resources/logs.png", 300, 400, 276, -2));
background.add(new Log("file:resources/log3.png", 150, 50, 329, 0.75));
background.add(new Log("file:resources/log3.png", 150, 270, 329, 0.75));
background.add(new Log("file:resources/log3.png", 150, 490, 329, 0.75));
background.add(new Turtle(500, 376, -1, 130, 130));
background.add(new Turtle(300, 376, -1, 130, 130));
background.add(new WetTurtle(700, 376, -1, 130, 130));
background.add(new WetTurtle(600, 217, -1, 130, 130));
background.add(new WetTurtle(400, 217, -1, 130, 130));
background.add(new WetTurtle(200, 217, -1, 130, 130));
background.add(new End(13,96));
background.add(new End(141,96));
background.add(new End(141 + 141-13,96));
background.add(new End(141 + 141-13+141-13+1,96));
background.add(new End(141 + 141-13+141-13+141-13+3,96));
animal = new Animal("file:resources/froggerUp.png", 150.00, 700.00, false);
background.add(animal);
background.add(new Obstacle("file:resources/truck1"+"Right.png", 0, 649, 1, 120, 120));
background.add(new Obstacle("file:resources/truck1"+"Right.png", 300, 649, 1, 120, 120));
background.add(new Obstacle("file:resources/truck1"+"Right.png", 600, 649, 1, 120, 120));
background.add(new Obstacle("file:resources/car1Left.png", 100, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/car1Left.png", 250, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/car1Left.png", 400, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/car1Left.png", 550, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/truck2Right.png", 0, 540, 1, 200, 200));
background.add(new Obstacle("file:resources/truck2Right.png", 500, 540, 1, 200, 200));
background.add(new Obstacle("file:resources/car1Left.png", 500, 490, -5, 50, 50));
background.add(new Digit(0, 30, 360, 25));
background.start();
start();
}
// #FXML
// public void button2action(ActionEvent event){
// primaryStage.setScene(scene);
// primaryStage.centerOnScreen();
// animal2 = new Animal("file:resources/froggerUp.png", 400.00, 700.00, true);
// background.add(animal2);
// }
// #FXML
// public void initialize(){
// bt2.addEventHandler(ActionEvent.ACTION, (e)->{
//
// });
// }
public void createTimer() {
timer = new AnimationTimer() {
// #Override
public void handle(long now) {
if (animal.changeScore()) {
setNumber(animal.getPoints());
}
if (animal.getStop()) {
System.out.print("STOP");
background.stopMusic();
stop();
background.stop();
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("You Have Won The Game!");
alert.setHeaderText("Your High Score: " + animal.getPoints() + "!");
alert.setContentText("Highest Possible Score: 800");
alert.show();
}
}
};
}
public void start() {
background.playMusic();
createTimer();
timer.start();
}
public void stop() {
timer.stop();
}
public void setNumber(int n) {
int shift = 0;
while (n > 0) {
int d = n / 10;
int k = n - d * 10;
n = d;
background.add(new Digit(k, 30, 360 - shift, 25));
shift+=30;
}
}
public static Stage getStage(){
return primaryStage;
}
// public static Scene getScene(){
// return scene;
// }
public void setSecondPlayer(boolean _secondPlayer) {
this.secondPlayer = _secondPlayer;
}
public boolean getSecondPlayer(){
return this.secondPlayer;
}
}
Here is the stack trace:
"C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3\jbr\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3\lib\idea_rt.jar=56118:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3\bin" -Dfile.encoding=UTF-8 -p "C:\Users\Joshu\Documents\SECOND YEAR\Software Maintenance\Frogger\out\production\froggerSWM" -m com.frogger.mainapp/com.frogger.mainapp.Main
This is horrible!
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8865)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3876)
at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:395)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782)
... 47 more
Caused by: java.lang.NullPointerException
at com.frogger.mainapp/com.frogger.mainapp.SampleController.button2action(SampleController.java:12)
... 58 more
Your log says you get a NullPointerException at line number 12:
at com.frogger.mainapp/com.frogger.mainapp.SampleController.button2action(SampleController.java:12)
Now we will go to line number 12:
Main.primaryStage.setScene(Main.scene);
The application is going to access setScene method from primaryStage object, which is static in Main class.
but have you initialized it in Main class?
No.
As you can see the declaration of primaryStage in Main class:
public static Stage primaryStage;
But nowhere in the code, I found primaryStage = something.
I think you confused with the method variable of start method with your static variable.
try to set primaryStage you received in start method to the static variable you created:
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
I think this helps you:
If you have any another approach let me know.
Related
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
my name is Omar, I made this code in javafx in order to switch between scene 0 and scene 1.
When an input scanner laser barcode number is introduced (6590055780)
it changes from scene 0 to scene 1, once in scene 1, if user pressed a button will change to scene 0.
But when i compile this code, it gives me the following error
"Exception in thread "JavaFX Application Thread" java.lang.illegalArgumentException: Grid hgap=10.0 alignment=CENTERis already set as root of another scene"
I do not know why i get this error, it is like the setOnKeyPressed does not allow me to leave from it, when i want to switch from scene 0 to scene 1, i got this error message, anyhelp is appreciated in order to solve this problem. thank you very much
and this is the code
import javafx.application.Application;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyEvent;
public class scannerinputfx2 extends Application {
////////////* public class*///////
public static String salida;
#Override
public void start(Stage primaryStage){
primaryStage.setTitle("what's up");
//scene 0
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Scene scene = new Scene(grid, 300, 275);
TextArea area = new TextArea();
TextField userTextField = new TextField();
//grid.add(userTextField, 0, 0);
//grid.add(area, 0,1);
GridPane.setConstraints(userTextField, 0,0);
GridPane.setConstraints(area,0,1);
grid.getChildren().addAll(area, userTextField);
//scene 1
GridPane grid1 = new GridPane();
grid1.setAlignment(Pos.CENTER);
grid1.setHgap(10);
grid1.setVgap(10);
grid1.setPadding(new Insets(25, 25, 25, 25));
Scene scene1 = new Scene(grid1, 300, 275);
Button btnfinal = new Button("Press button to get back");
GridPane.setConstraints(btnfinal, 0, 0);
grid1.getChildren().addAll(btnfinal);
btnfinal.setOnAction(actionEvent -> {
scene1.setRoot(grid);
});
primaryStage.setScene(scene);
primaryStage.show();
userTextField.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent ke) {
area.setText( userTextField.getText());
if (userTextField.getText().equals("6590055780"))
{
System.out.println("The number is " + userTextField.getText());
userTextField.setText("");
scene.setRoot(grid1);
}
else
{
System.out.println("The number is not the indicated");
}
}
});
}
////////*Here finish primary stage/////////
public static void main(String[] args) {
launch(args);
}
}
I'm trying to load different urls into a javafx webview after a given time. I have searched for a solution for at least 2 weeks but i wasn't able to find anything or wasn't able to transfer the solutions of similar problems to my code. Below are the necessary parts of the code:
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("/application/FXML.fxml"));
primaryStage.setTitle("Window");
primaryStage.setScene(new Scene (root));
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
FXMLController.java
package application;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
public class FXMLController implements Initializable {
#FXML private Button btnAddUrl;
#FXML private Button btnStart;
#FXML private Slider sliderTime2NextUrl;
#FXML private WebView webviewWindow;
private WebEngine engine;
private FileChooser fileChooser;
private List<String> url;
private int urlTime;
public void initialize(URL arg0, ResourceBundle arg1) {
btnAddUrl.setOnAction(this::addUrls);
btnStart.setOnAction(this::urlLoad);
fileChooser = new FileChooser();
engine = webviewWindow.getEngine();
getsliderTime2NextUrl();
}//initialize
#FXML
private void addUrls(ActionEvent event) {
fileChooser.setTitle("Add Like List");
fileChooser.getExtensionFilters().addAll(
new ExtensionFilter("TXT Files", "*.TXT"),
new ExtensionFilter("txt Files", "*.txt"));
File file = fileChooser.showOpenDialog(null);
try {
url = Files.readAllLines(file.toPath());
} catch (Exception e) {
System.out.println("shit");
}
System.out.println(url);
}
#FXML
private void getsliderTime2NextUrl() {
sliderTime2NextUrl.valueProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.println("Slider Value Changed (newValue: " + newValue.intValue() + ")");
double getTime;
getTime = sliderTime2NextUrl.valueProperty().getValue();
urlTime = (int) getTime;
}//changed
});//addListener
}//getsliderTime2NextUrl
#FXML
private void urlLoad (ActionEvent event) {
Task<Void> task = new Task<Void>() {
#Override protected Void call() throws Exception{
urlTime = urlTime * 1000 ;
System.out.println("next Url in: " + urlTime);
for(int i = 0; i < url.size(); i++) {
System.out.println("Url.size = "+ url.size());
System.out.println("Url = "+ i);
if(isCancelled()) {
updateMessage("Cancelled");
break;
}
updateMessage("Iteration " + i);
updateProgress(i, 1000);
try {
Thread.sleep(urlTime);
System.out.println("Thread Sleeps for :" + urlTime);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}
return null;
}
};
new Thread(task).start();
}
/*
#FXML
private void urlLoad (ActionEvent event) {
urlTime = urlTime * 1000 ;
System.out.println("next Url in: " + urlTime);
for(int i = 0; i < url.size(); i++) {
System.out.println("Url.size = "+ url.size());
System.out.println("Url = "+ i);
String Link = url.get(i);
engine.load(Link);
System.out.println("Url loaded = " + Link);
}
}*/
}
FXML.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.web.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308"
minHeight="400.0" minWidth="500.0"
prefHeight="500.0" prefWidth="500.0"
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.FXMLController">
<children>
<MenuBar maxHeight="25.0" maxWidth="1920.0" prefHeight="25.0" prefWidth="500.0">
<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>
<Button fx:id="btnAddUrl" layoutX="66.0" layoutY="39.0" mnemonicParsing="false" onAction="#addUrls" prefHeight="25.0" prefWidth="69.0" text="AddUrl" />
<Button fx:id="btnStart" layoutX="36.0" layoutY="108.0" mnemonicParsing="false" onAction="#urlLoad" prefHeight="31.0" prefWidth="108.0" text="Start!">
<font>
<Font size="18.0" />
</font>
</Button>
<Slider fx:id="sliderTime2NextUrl" blockIncrement="1.0" layoutX="204.0" layoutY="39.0" majorTickUnit="2.0" max="15.0" min="3.0" minorTickCount="1" prefHeight="38.0" prefWidth="251.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="3.0" />
<WebView fx:id="webviewWindow" layoutY="147.0" minHeight="-1.0" minWidth="-1.0" prefHeight="350.0" prefWidth="500.0" />
</children>
</AnchorPane>
I used the second "urlLoad"-Method (FXMLController.java) in the /* */ first but recognized that all Links are loaded immediately and only the last one stays active. After that I added "Thread.sleep(urlTime) + try & catch" but it freezed my whole GUI until the last URL was loaded. While searching for a solution, that was the first time I heard of workers, tasks & services.
I found out why this happened and tried to add a "Task" around the code. It was a long jorney until I found the code of the first "urlLoad"-Method in FXMLController.java. Thats exactly what my code with the Urls shoud do
![urlLoad-Method 1] there should be an image if i had 10 reputation
it gives out the numbers in the console with the given time from the slider.
Then i added my engine.load() part to the first "urlLoad"-Method
//updateMessage("Iteration " + i);
//updateProgress(i, 1000);
String Link = url.get(i);
engine.load(Link);
System.out.println("Url loaded = " + Link);
But then the method stops at the first Url and doesnt show anything:
![urlLoad-Method 1 with engine.load] there should be an image if i had 10 reputation
My assumption is, that the "urlLoad"-Method does not update the WebView Window in my GUI. I hope somebody can help me.
Thanks
Edit: After adding
task.setOnFailed((WorkerStateEvent t) -> {
throw new RuntimeException(task.getException());
});
I got the following exception:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at application.FXMLController.lambda$2(FXMLController.java:111)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.concurrent.EventHelper.fireEvent(EventHelper.java:219)
at javafx.concurrent.Task.fireEvent(Task.java:1356)
at javafx.concurrent.Task.setState(Task.java:707)
at javafx.concurrent.Task$TaskCallable.lambda$call$502(Task.java:1453)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.web.WebEngine.checkThread(WebEngine.java:1243)
at javafx.scene.web.WebEngine.load(WebEngine.java:913)
at application.FXMLController$2.call(FXMLController.java:92)
at application.FXMLController$2.call(FXMLController.java:1)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(Unknown Source)
... 1 more
you need to use
Platform.Runlater(()->{/*your task content here*/});
Javafx is pissy about what operations it allows you to run in which thread. Essentially, you have no business running code designated for ui control functionality on a non-ui thread... hence "thread 5" in your case.
Be careful, however, as you still need that thread.sleep routine in your background thread, as the javafx thread will sleep, and then proceed with the url.load() routine.
so...
javafxapplication thread (runs - handles its own operations)
thread 5 (runs whatever you want)
->
javafxapplication thread (runs but is idle from your POV)
thread 5 (invokes platform.runlater(/* engine.load("x") */))
->
javafxapplicationthread (executes engine.load())
thread 5 (etc etc etc)
good luck
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("");
}
}
I'm new to JavaFX and I wonder if there is some equivalent to Android Toast?
I have seen the class Notification, but it doesn't look like it can be displayed only in the application. I also found I could user a Timer and make shading of a Label, but if there's some class to use, I'd be better!
Thanks!
I know it has been a long time since you post this, but I have just made an android-like toast message for javafx, so I post it here in case that someone need this kind of code.
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
public final class Toast
{
public static void makeText(Stage ownerStage, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay)
{
Stage toastStage=new Stage();
toastStage.initOwner(ownerStage);
toastStage.setResizable(false);
toastStage.initStyle(StageStyle.TRANSPARENT);
Text text = new Text(toastMsg);
text.setFont(Font.font("Verdana", 40));
text.setFill(Color.RED);
StackPane root = new StackPane(text);
root.setStyle("-fx-background-radius: 20; -fx-background-color: rgba(0, 0, 0, 0.2); -fx-padding: 50px;");
root.setOpacity(0);
Scene scene = new Scene(root);
scene.setFill(Color.TRANSPARENT);
toastStage.setScene(scene);
toastStage.show();
Timeline fadeInTimeline = new Timeline();
KeyFrame fadeInKey1 = new KeyFrame(Duration.millis(fadeInDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 1));
fadeInTimeline.getKeyFrames().add(fadeInKey1);
fadeInTimeline.setOnFinished((ae) ->
{
new Thread(() -> {
try
{
Thread.sleep(toastDelay);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Timeline fadeOutTimeline = new Timeline();
KeyFrame fadeOutKey1 = new KeyFrame(Duration.millis(fadeOutDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 0));
fadeOutTimeline.getKeyFrames().add(fadeOutKey1);
fadeOutTimeline.setOnFinished((aeb) -> toastStage.close());
fadeOutTimeline.play();
}).start();
});
fadeInTimeline.play();
}
}
You can make a toast message from any class with this code:
String toastMsg = "some text...";
int toastMsgTime = 3500; //3.5 seconds
int fadeInTime = 500; //0.5 seconds
int fadeOutTime= 500; //0.5 seconds
Toast.makeText(primarystage, toastMsg, toastMsgTime, fadeInTime, fadeOutTime);
Try the third party ControlsFX Notifications or Notification Pane.
"The NotificationPane control allows you to notify your users of something without requiring their immediate input (which you can do with the ControlsFX dialogs API). The NotificationPane will animate in and out of view"
Notifications "will show a notification message to users in one of nine locations on the screen ... After a set duration, the notification will fade out."
To create own toast by using own fxml layout:
package controllers;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
import java.io.IOException;
public class ToastController {
public static final int TOAST_SUCCESS = 11;
public static final int TOAST_WARN = 12;
public static final int TOAST_ERROR = 13;
#FXML
private HBox containerToast;
#FXML
private Label textToast;
private void setToast(int toastType, String content){
textToast.setText(content);
switch (toastType){
case TOAST_SUCCESS:
containerToast.setStyle("-fx-background-color: #9FFF96");
break;
case TOAST_WARN:
containerToast.setStyle("-fx-background-color: #FFCF82");
break;
case TOAST_ERROR:
containerToast.setStyle("-fx-background-color: #FF777C");
break;
}
}
public static void showToast(int toastTyoe, Control control, String text){
Stage dialog = new Stage();
dialog.initOwner(control.getScene().getWindow());
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.setResizable(false);
dialog.initStyle(StageStyle.UNDECORATED);
double dialogX = dialog.getOwner().getX();
double dialogY = dialog.getOwner().getY();
double dialogW = dialog.getOwner().getWidth();
double dialogH = dialog.getOwner().getHeight();
double posX = dialogX + dialogW/2;
double posY = dialogY + dialogH/6 *5;
dialog.setX(posX);
dialog.setY(posY);
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(ToastController.class.getResource("/fxml/toastPopup.fxml"));
loader.load();
ToastController ce = loader.getController();
ce.setToast(toastTyoe,text);
dialog.setScene(new Scene(loader.getRoot()));
dialog.show();
new Timeline(new KeyFrame(
Duration.millis(1500),
ae -> {
dialog.close();
})).play();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<HBox fx:id="containerToast" alignment="CENTER" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.ToastController">
<children>
<Label fx:id="textToast" text="TEST" textAlignment="CENTER">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
to run toast just use:
One of 3 types of toast:
ToastController.TOAST_ERROR
ToastController.TOAST_SUCCESS
ToastController.TOAST_WARN
#FXML
private Label idOfAnyControl;
showToast(ToastController.TOAST_WARN,idOfAnyControl,"ERROR TEXT")
if you want you can extract 2 additional options by dependency injection (time and position of toast)
#alcoolis equivalent in kotlin
Toast.makeText(primaryStage, "No data selected!")
class Toast {
companion object {
fun makeText(stage: Stage, message: String, displayTime: Int = 3000, fadeInDelay: Int = 500, fadeOutDelay: Int = 500, size: Double = 15.0, opacity: Double = 5.0) {
val toastStage = Stage()
toastStage.initOwner(stage)
toastStage.isResizable = false
toastStage.initStyle(StageStyle.TRANSPARENT)
val text = Text(message)
text.font = Font.font("Verdana", size)
text.fill = Color.RED
val root = StackPane(text)
root.style = "-fx-background-radius: 20; -fx-background-color: rgba(0, 0, 0, 0.2); -fx-padding: 50px;"
root.opacity = opacity
val scene = Scene(root)
scene.fill = Color.TRANSPARENT
toastStage.scene = scene
toastStage.show()
val fadeInTimeline = Timeline()
val fadeInKey1 =
KeyFrame(Duration.millis(fadeInDelay.toDouble()), KeyValue(toastStage.scene.root.opacityProperty(), 1))
fadeInTimeline.keyFrames.add(fadeInKey1)
fadeInTimeline.setOnFinished {
Thread {
try {
Thread.sleep(displayTime.toLong())
} catch (e: InterruptedException) {
// TODO Auto-generated catch block
e.printStackTrace()
}
val fadeOutTimeline = Timeline()
val fadeOutKey1 =
KeyFrame(
Duration.millis(fadeOutDelay.toDouble()),
KeyValue(toastStage.scene.root.opacityProperty(), 0)
)
fadeOutTimeline.keyFrames.add(fadeOutKey1)
fadeOutTimeline.setOnFinished { toastStage.close() }
fadeOutTimeline.play()
}.start()
}
fadeInTimeline.play()
}
}
}
#acoolis version with up-to-date JavaFX transitions as suggested by #jewelsea.
public final class ToastHelper {
public static void makeText(Stage ownerStage, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay) {
final Stage toastStage = new Stage();
toastStage.initOwner(ownerStage);
toastStage.setResizable(false);
toastStage.initStyle(StageStyle.TRANSPARENT);
final Text text = new Text(toastMsg);
final StackPane root = new StackPane(text);
root.getStyleClass().add("my-dialog-toast");
final Scene scene = new Scene(root);
scene.setFill(Color.TRANSPARENT);
scene.getStylesheets().add("style.css");
toastStage.setScene(scene);
toastStage.show();
// make effect: fade-in, pause, then fade-out effect varying the opacity of the whole window
final javafx.animation.FadeTransition inTransition = new FadeTransition(new Duration(fadeInDelay),
toastStage.getScene().getRoot());
inTransition.setFromValue(0.0);
inTransition.setToValue(1);
final javafx.animation.FadeTransition outTransition = new FadeTransition(new Duration(fadeOutDelay),
toastStage.getScene().getRoot());
outTransition.setFromValue(1.0);
outTransition.setToValue(0);
final javafx.animation.PauseTransition pauseTransition = new PauseTransition(new Duration(toastDelay));
final javafx.animation.SequentialTransition mainTransition = new SequentialTransition(
inTransition, pauseTransition, outTransition);
mainTransition.setOnFinished(ae -> toastStage.close());
mainTransition.play();
}
}