In my FXML I created a gridpane. Now I want to add dynamic element (Like button, textfield)
by java code (not by FXML), while I am trying to do so, I am getting error. Please Help.
my FXML:
<AnchorPane fx:controller="tableview.TableViewSample" id="AnchorPane" maxHeight="- Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<children>
<GridPane fx:id="greadpane" layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
<columnConstraints>
<ColumnConstraints fx:id="col0" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints fx:id="row0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
</AnchorPane>
My Java Code:
public class TableViewSample extends Application {
#FXML private GridPane greadpane;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws IOException {
Pane myPane = (Pane)FXMLLoader.load(getClass().getResource
("tabviewexamlpe.fxml"));
Scene scene = new Scene(myPane);
stage.setTitle("Table View ");
stage.setWidth(450);
stage.setHeight(500);
stage.setScene(scene);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
greadpane.add(label, 0, 0);
stage.show();
}
}
You get a null pointer cause you try to do operation before stage.show() so fxml are not yet initialized. don't do dirty things and put your greadPane.add on a separate controller
public class Controller implements Initializable {
#FXML
private GridPane greadpane;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
greadpane.add(label, 0, 0);
}
}
and assign your fxml to this controler. and it's will be ok
I ran into the same problem and used Agonist_ advice, however instead of separating the gridPane into a new controller i just created a thread that runs 10ms later to execute the code which is waiting for stage.show().
public GameController(Game game) {
game.addObserver(this);
new Thread() {
#Override
public void run() {
try {
Thread.sleep(10);
Platform.runLater(() -> {
game.startBeginnerRound();
});
} catch (InterruptedException ex) {
Logger.getLogger(GameController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
In this example the gridPane is updated when the observable notifies it, in this case when game.startBeginnerRound() is executed.
Related
I'm trying to bind a DoubleProperty to a TextField and the only binding functionnal is the bidirectionnal and not the unidirectionnal binding.
My specific TextField :
public class DoubleTextField extends TextField{
public DoubleTextField() {
super();
Pattern validDoubleText = Pattern.compile("-?(\\d*)|(\\d+\\.\\d*)");
UnaryOperator<TextFormatter.Change> doubleCheck = change -> {
String newText = change.getControlNewText();
if (validDoubleText.matcher(newText).matches()) {
return change;
} else
return null;
};
this.setTextFormatter(new TextFormatter<Double>(new DoubleStringConverter(), null, doubleCheck));
}
}
public class Controller implements Initializable {
#FXML
GridPane gpTest;
#FXML
TextField tfUSDT;
Model model;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
this.model = new Model();
DoubleTextField dtfPrice = new DoubleTextField();
gpTest.add(dtfPrice, 1, 0);
tfUSDT.textProperty().bind(model.getDpActualUsdt().asString("%f"));
//dtfPrice.textProperty().bind(model.getDpActualPrice().asString("%f"));
dtfPrice.textProperty().bindBidirectional(model.getDpActualPrice(), new NumberStringConverter());
}
public void modifyUSDT(ActionEvent e) {
this.model.getDpActualUsdt().set(50);
}
public void modifyPrice(ActionEvent e) {
this.model.getDpActualPrice().set(50);
}
}
public class Model {
private DoubleProperty dpActualUsdt, dpActualPrice;
public Model() {
dpActualPrice = new SimpleDoubleProperty(0);
dpActualUsdt = new SimpleDoubleProperty(0);
}
public void setDpActualUsdt(DoubleProperty dpActualUsdt) {
this.dpActualUsdt = dpActualUsdt;
}
public void setDpActualPrice(DoubleProperty dpActualPrice) {
this.dpActualPrice = dpActualPrice;
}
public DoubleProperty getDpActualPrice() {
return dpActualPrice;
}
public DoubleProperty getDpActualUsdt() {
return dpActualUsdt;
}
}
<FlowPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<GridPane fx:id="gpTest">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="tfUSDT" />
<Button mnemonicParsing="false" onAction="#modifyUSDT" text="Modify USDT" GridPane.rowIndex="1" />
<Button mnemonicParsing="false" onAction="#modifyPrice" text="Modify Price" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader fxml = new FXMLLoader(getClass().getResource("/resources/ihm.fxml"));
Pane mainPane = fxml.load();
Scene scene = new Scene(mainPane);
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Here are my classes
With this the code work as expected but if i comment dtfPrice.textProperty().bindBidirectional(model.getDpActualPrice(), new NumberStringConverter()) and decomment //dtfPrice.textProperty().bind(model.getDpActualPrice().asString("%f"));
He doesn't work
Thanks for everyone helping me !
Is there any way to add a blur effect only to a part of an image defined by the area of a Pane? If you blur the pane over the image only the pane get blurred, but is there a way to blur the picture part underneath?
Here's an example of what I mean: It's simply just an image overlayed with a pane which has backgrouud and opacity set. Now I want to blur the part the pane lays on.
Main.java:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
GridPane root = (GridPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root,500,500);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Sample.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<ImageView fitHeight="495.0" fitWidth="535.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
<image>
<Image url="#../../../../Downloads/ZGEX2eX.jpg" />
</image>
</ImageView>
<Pane prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: #012E56; -fx-opacity: 0.666;" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
</children>
</GridPane>
You can use the Clip of an ImageView to apply an effect only to a specific area of your image:
public class BlurredImageTest extends Application {
private DoubleProperty effectHeight = new SimpleDoubleProperty(80);
#Override
public void start(Stage primaryStage) {
Image image = new Image("yourImage.jpg");
ImageView img = new ImageView(image);
Rectangle clip = new Rectangle();
clip.widthProperty().bind(image.widthProperty());
clip.heightProperty().bind(image.heightProperty().subtract(effectHeight));
img.setClip(clip);
ImageView imgEffect = new ImageView(image);
Rectangle clipEffect = new Rectangle();
clipEffect.widthProperty().bind(image.widthProperty());
clipEffect.heightProperty().bind(effectHeight);
clipEffect.translateYProperty().bind(image.heightProperty().subtract(effectHeight));
imgEffect.setClip(clipEffect);
imgEffect.setEffect(new GaussianBlur());
StackPane root = new StackPane(img, imgEffect);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public final void setEffectHeight(double value) {
effectHeight.set(value);
}
public static void main(String[] args) {
launch(args);
}
}
I'm building a DialogPane in FXML and I'm trying to figure out how to respond to button presses on the dialog since onAction is not a valid parameter for ButtonType. I've attached my FXML and Controller Class. There is very little documentation about DialogPane and even less about doing it in FXML so I'm not sure how to proceed.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ButtonType?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<DialogPane fx:id="loginPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="LoginController">
<content>
<GridPane hgap="5.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="300.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Driver Name" />
<TextField fx:id="driverTxt" GridPane.columnIndex="1" />
<Label text="URL" GridPane.rowIndex="1" />
<TextField fx:id="urlTxt" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label text="Username" GridPane.rowIndex="2" />
<TextField fx:id="userTxt" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="Password" GridPane.rowIndex="3" />
<TextField fx:id="passTxt" GridPane.columnIndex="1" GridPane.rowIndex="3" />
</children>
</GridPane>
</content>
<buttonTypes>
<ButtonType fx:id="loginButton" text="Login" />
<ButtonType fx:id="cancelBtn" text="Cancel" />
</buttonTypes>
</DialogPane>
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.ButtonType;
import javafx.scene.control.DialogPane;
import javafx.scene.control.TextField;
public class LoginController {
#FXML
DialogPane loginPane;
#FXML
TextField driverTxt;
#FXML
TextField urlTxt;
#FXML
TextField userTxt;
#FXML
TextField passTxt;
#FXML
ButtonType loginButton;
#FXML
private void loginButtonAction(){
// How do I do something here
}
public void initialize() {
driverTxt.setText("org.postgresql.Driver");
urlTxt.setText("jdbc:postgresql://localhost/postgres");
userTxt.setText("postgres");
passTxt.setText("postgres");
}
}
Typically you wouldn't need to do this. You would usually show a DialogPane in a Dialog<ButtonType> calling its showAndWait() method, which returns an Optional<ButtonType> representing the button pressed (if any). So normal usage would be something like
public class LoginController {
public static final ButtonType LOGIN = new ButtonType("Login");
#FXML
DialogPane loginPane;
#FXML
TextField driverTxt;
#FXML
TextField urlTxt;
#FXML
TextField userTxt;
#FXML
TextField passTxt;
public void initialize() {
driverTxt.setText("org.postgresql.Driver");
urlTxt.setText("jdbc:postgresql://localhost/postgres");
userTxt.setText("postgres");
passTxt.setText("postgres");
}
public String getDriver() {
return driverTxt.getText();
}
public String getUrl() {
return urlTxt.getText();
}
public String getUser() {
return userTxt.getText();
}
public String getPass() {
return pass.getText();
}
}
and make the following changes to your FXML file:
<buttonTypes>
<LoginController fx:constant="LOGIN" />
<ButtonType fx:constant="CANCEL" />
</buttonTypes>
Then you would use this with:
Dialog<ButtonType> dialog = new Dialog<>();
FXMLLoader dialogLoader = new FXMLLoader(getClass().getResource("Login.fxml"));
dialog.setDialogPane(dialogLoader.load());
LoginController controller = dialogLoader.getController();
dialog.showAndWait().filter(LoginController.LOGIN::equals)
.ifPresent(button -> {
String driver = controller.getDriver();
// etc etc
// process login...
});
As an alternative to exposing the text from the text fields, you could define a processLogin() method in the controller itself that read the text fields and did whatever you need to do:
public class LoginController {
public static final ButtonType LOGIN = new ButtonType("Login");
#FXML
DialogPane loginPane;
#FXML
TextField driverTxt;
#FXML
TextField urlTxt;
#FXML
TextField userTxt;
#FXML
TextField passTxt;
public void initialize() {
driverTxt.setText("org.postgresql.Driver");
urlTxt.setText("jdbc:postgresql://localhost/postgres");
userTxt.setText("postgres");
passTxt.setText("postgres");
}
public void processLogin() {
String driver = driverTxt.getText();
// etc...
// process login...
}
}
then just do
// ...
dialog.showAndWait().filter(LoginController.LOGIN::equals)
.ifPresent(button -> controller.processLogin());
If you really need to register an onAction handler with the login button, do it in the initialize() method in the controller:
public void initialize() {
driverTxt.setText("org.postgresql.Driver");
urlTxt.setText("jdbc:postgresql://localhost/postgres");
userTxt.setText("postgres");
passTxt.setText("postgres");
Button login = (Button) loginPane.lookupButton(loginButton);
login.setOnAction(e -> { /* ... */ });
}
but this is really against the intended use of the dialog pane API.
One final alternative would be to override the createButton method in DialogPane. To do this, you'd need a subclass of DialogPane, which would mean using the FXML custom component pattern.
So this would look something like:
public class LoginPane extends DialogPane {
public static final ButtonType LOGIN = new ButtonType("Login");
#FXML
TextField driverTxt;
#FXML
TextField urlTxt;
#FXML
TextField userTxt;
#FXML
TextField passTxt;
public LoginPane() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("LoginPane.fxml"));
loader.setRoot(this);
loader.setController(this);
loader.load();
} catch (IOException exc) {
// bad if you get here...
throw new UncheckedIOException(exc);
}
}
#Override
public Node createButton(ButtonType buttonType) {
Node button = super.createButton(buttonType);
if (buttonType == LOGIN) {
((Button) button).setOnAction(e -> processLogin());
}
return button ;
}
public void initialize() {
driverTxt.setText("org.postgresql.Driver");
urlTxt.setText("jdbc:postgresql://localhost/postgres");
userTxt.setText("postgres");
passTxt.setText("postgres");
}
public void processLogin() {
String driver = driverTxt.getText();
// etc...
// process login...
}
}
and the FXML would then look like
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ButtonType?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<fx:root type="DialogPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
<content>
<GridPane hgap="5.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="300.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Driver Name" />
<TextField fx:id="driverTxt" GridPane.columnIndex="1" />
<Label text="URL" GridPane.rowIndex="1" />
<TextField fx:id="urlTxt" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label text="Username" GridPane.rowIndex="2" />
<TextField fx:id="userTxt" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="Password" GridPane.rowIndex="3" />
<TextField fx:id="passTxt" GridPane.columnIndex="1" GridPane.rowIndex="3" />
</children>
</GridPane>
</content>
<buttonTypes>
<LoginPane fx:constant="LOGIN" />
<ButtonType fx:constant="CANCEL" />
</buttonTypes>
</fx:root>
You would use this version with
Dialog dialog = new Dialog();
dialog.setDialogPane(new LoginPane());
dialog.showAndWait();
so if you are looking to encapsulate as much as possible into the login pane and fxml, this is probably the cleanest option.
Note that the usage of DialogPane is fairly completely documented in the API docs for Dialog and DialogPane.
I want to get the size of a node, after it has been sized properly, which I understand is done after the stage is shown. however, i cannot do it in start() method, because the node is not initialized yet, because its loaded it from an FXML file.
If I implement Initializable Interface and try to get the size in initialize() method, it returns 0.0
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<GridPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="musicPlayer.Test">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TableView fx:id="testNode">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</children>
</GridPane>
just an arbitrary node in a grid pane generated with scene builder
public class Test extends Application implements Initializable {
#FXML
private TableView testNode;
public void initialize(URL location, ResourceBundle resources) {
//System.out.println(testNode.getWidth()); is always 0.0
}
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("test.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
//System.out.println(testNode.getWidth()); throws Nullpointer Exception
}
public static void main(String[] args) {
launch(args);
}
}
I've also tried adding a listener to the stage, but i still get a nullpointer exception.
Is there a way of getting the size, without using a sleeping thread?
I have 2 FXML files, with 2 controllers. Each FXML file has its own controller. First scene has a button that takes you to the 2nd scene. Now my question is, how can I start executing the commands "label.setText ("Hello There \n");" in my 2nd controller without doing any additional ActionEvent other than the button click from scene1 to take me to scene2 .
MainController:
public void startNewScene() throws IOException {
root = FXMLLoader.load(getClass().getResource("FXML.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
2nd controller as per the example in the comment below from " ItachiUchiha"
public class MyController implements Initializable {
#FXML private Button button;
#FXML private Label label;
#FXML
#Override
public void initialize(URL location, ResourceBundle resources) {
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
label.setText("hello there, you clicked me");
}
}
);
}
}
Now the 2nd scene gets uploaded but nothing is outputted to the screen or to the console. But when I click on the button on scene everything works.
So I tried to set "onMouseClicked" and "onAction" to initialize and/or handle for both label and button but I get errors "handler method not found." in the FXML file
FXML file:
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ciacv.MyController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label fx:id="label" />
<Button fx:id="button" mnemonicParsing="false" text="Button" GridPane.columnIndex="1" />
</children>
</GridPane>
The fx:id of your button in your fxml is butn1 where as in your controller you have are trying to inject the Button with declaration
#FXML private Button button;
You need to use the same fx:id that you have declared in the fxml to correctly inject the object into its reference i.e.
#FXML private Button butn1;
Edit - As per the comments
You need to set the Scene on the Stage
public void startNewScene() throws IOException {
root = FXMLLoader.load(getClass().getResource("FXML.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
Edit - 2
No you have not written anything to set the text in the label when the fxml gets loaded.
You have just written
label.setText("hello there, you clicked me");`
inside the button's action. If you need to set the text in label at load, you can write the following statement inside intialize()
#Override
public void initialize(URL location, ResourceBundle resources) {
// Set Label's text intialize() is called
label.setText("Helll There...");`
// Set Label's text on Button's action
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
label.setText("hello there, you clicked me");
}
}
}