im trying to add some text to a textfield, but when i click the button it shows nullpointerexception , why is this happening?
MainWindowController.java
#FXML
public TextField konsumatoriPunetField = new TextField();
#FXML
private void initialize()
{
FXMLLoader loader5 = new FXMLLoader();
loader5.setLocation(getClass().getResource("ZgjedhKonsumatorinFXML.fxml"));
BorderPane border5 = new BorderPane();
border5 = loader5.load();
Scene scene5 = new Scene(border5);
zgjedhkonsumatorinstage.setScene(scene5);
zgjedhkonsumatorinstage.setTitle("Pit Stop");
zgjedhkonsumatorinstage.initModality(Modality.WINDOW_MODAL);
zgjedhkonsumatorinstage.initOwner(MainFXMLController.mainFXMLStage);
}
#FXML
public void zgjedhKonsumatorin()
{
zgjedhkonsumatorinstage.showAndWait();
}
MainWindowFXML.fxml
<TextField fx:id="konsumatoriPunetField" editable="false" onMouseClicked="#zgjedhKonsumatorin" promptText="Kliko per te zgjedhur" GridPane.columnIndex="1" GridPane.rowIndex="1" />
ZgjedhKonsumatorinController.java
#FXML
public void zgjedhKonsumatorin()
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("MainWindowFXML.fxml"));
MainWindowController c = (MainWindowController) loader.getController();
c.konsumatoriPunetField.textProperty().setValue("ertani");
main.zgjedhkonsumatorinstage.close();
}
ZgjedhKonsumatorinFXML.fxml
<Button mnemonicParsing="false" onAction="#zgjedhKonsumatorin" prefWidth="150.0" text="Zgjedh Konsumatorin" />
Output:
Caused by: java.lang.NullPointerException
at main.ZgjedhKonsumatorinController.zgjedhKonsumatorin(ZgjedhKonsumatorinController.java:193)
... 102 more
p.s. this is the line 193 in ZgjedhKonsumatorinController (exception)
c.konsumatoriPunetField.textProperty().setValue("ertani");
The controller is created by the FXMLLoader when you load the FXML file (the controller class is specified by the FXML file, so this is the only time it could be created). So if you call loader.getController() before calling load(), the value returned will be null. Hence in your code c is null and you get a null pointer exception.
Note that it won't actually help to call loader.load() here. It would fix the null pointer exception, but of course you would load a new instance of the UI defined by the FXML file, and a new instance of the controller. Hence the text field whose text you are setting would not be the text field that is displayed, and nothing would happen.
Since you are using showAndWait() on the window you create, the easiest way to set the text is just to do it back in the MainWindowController, after the showAndWait() call completes. showAndWait() blocks execution until the window is closed, so the text field won't change until the window is closed.
First define a method in ZgjedhKonsumatorinController for retrieving the text:
public class ZgjedhKonsumatorinController {
#FXML
public void zgjedhKonsumatorin()
{
main.zgjedhkonsumatorinstage.close();
}
public String getText() {
// in real life you can get text from the controls in ZgjedhKonsumatorinFXML.fxml
return "ertani" ;
}
}
and now back in MainWindowController you can do:
public class MainWindowController {
#FXML
// Note: it is ALWAYS a mistake to initialize #FXML-injected fields.
// Just declare them and let the FXMLLoader initialize them
// (that is the whole point of #FXML)
private TextField konsumatoriPunetField ;
private ZgjedhKonsumatorinController zgjedhKonsumatorinController ;
#FXML
private void initialize()
{
FXMLLoader loader5 = new FXMLLoader();
loader5.setLocation(getClass().getResource("ZgjedhKonsumatorinFXML.fxml"));
BorderPane border5 = new BorderPane();
border5 = loader5.load();
zgjedhKonsumatorinController = loader.getController();
Scene scene5 = new Scene(border5);
zgjedhkonsumatorinstage.setScene(scene5);
zgjedhkonsumatorinstage.setTitle("Pit Stop");
zgjedhkonsumatorinstage.initModality(Modality.WINDOW_MODAL);
zgjedhkonsumatorinstage.initOwner(MainFXMLController.mainFXMLStage);
}
#FXML
public void zgjedhKonsumatorin()
{
zgjedhkonsumatorinstage.showAndWait();
konsumatoriPunetField.setText(zgjedhKonsumatorinController.getText());
}
}
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
when i want to setText for TextField (miniFilePath) it throws null exception i don't know what is wrong with my code?
public class SettingsController {
#FXML
private TextField miniFilePath;
#FXML
private Button settingExitBtn;
public static String miniFilterPath = new String() ;
public static String reportDirectoryPath = new String();
Stage settings = new Stage();
public void display( ){
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Settings.fxml"));
Parent root = (Parent) fxmlLoader.load();
//settings = new Stage();
Stage settings = new Stage();
settings.setScene(new Scene(root));
settings.initModality(Modality.APPLICATION_MODAL);
settings.setResizable(false);
settings.setTitle("settings");
if (!miniFilterPath.isEmpty())
miniFilePath.setText(miniFilterPath);
settings.show();
} catch(Exception e) {
e.printStackTrace();
}
}
this class works as my second window, when i click on one button in another window one instance of this class is called and the window is made.
i want that after user set text for a textfield every time user try to open this window the text field is set to the string that is set before.
Override the initialize() method before your display() method
#FXML
public void initialize() {
refresh();
}
public void refresh() {
if (!(miniFilterPath == null | miniFilterPath.trim().equals("")))
miniFilePath.setText(miniFilterPath);
}
Also I assumed that you have a text field in your fxml file with the following:
fx:id="miniFilePath"
If you don't have that, init the text field in your display() method with the following:
miniFilePath = new TextField();
I have multiple tabs and one of them is my console output. I am trying to redirect System.out/err to TextArea loggerPane in that console output Tab using JavaFX. My question is how can I do that in a different thread because while it's outputting I can't navigate to the console tab.
Main App:
public initRootLayout(){
FXMLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource(RootLayout.fxml))
rootLayout = (BorderPane) loader.load();
scene = new Scene (rootLayout);
primaryStage.setScene(scene);
rootLayoutController = loader.getController();
rootLayoutController.setMainApp(this);
primaryStage.show();
}
I included the ConsoleController in RootController where I have all the tabs
#FXML private ConsoleController consoleController
RootLayoutFXML: I included the consoleFXML that uses its own controller
<Tab text="Console">
<content>
fx:include fx:id="myConsolePane" source="console.fxml"
</content>
</Tab>
ConsoleController
public class ConsoleController implements Initializable {
#FXML
private TextArea loggerPane;
public void appendText(String valueOf){
Platform.runLater(()-> loggerPane.appendText(valueOf))
}
#Override
public void initialize (URL ur, ResourceBundle rb){
OutputStream out = new OutputStream(){
#Override
public void write(int b) throws IOException{
appendText(String.valueOf((char)b));
}
};
System.setOut(out, true);
System.setErr(out, true);
}
Background Thread:
It's calling background class that interacts with a Rest API to
preform a function, sometime it outputs a long string as part of
the validation which I want to capture in the console tab.
I've been struggling for days over a stupid issue, and I need your help. I'm simply trying to display a indeterminate process indicator like the one below, within a separate Stage, while my main code performs a loop. If a certain condition is met while looping, the progress stage should close and the main code continues.
Right now I'm able to open a new stage prior to the main code starting the loop, but the progress indicator won't display in the stage yet. But once the condition is met, then the indicator suddenly appears in the stage and rotates. BUT as soon as the main code begins running again the indicator freezes, yet remains visible.
I'll briefly explain what each code below does. How do I make it so that the loading stage appears initially WITH the indicator visible, and then that stage CLOSES when the showMessage() method is called? Basically I want to show the user that background looping is happening, until the main code reaches showMessage().
Main.java
I won't post it, as it only creates the FIRST GUI. It uses menu.fxml as the resource in FXMLLoader ... and menu.fxml uses Controller.java as controller.
Controller.java
This code changes the scene in the Main GUI to have a new layout, which asks the user to click one of the visible buttons. It then checks if the source button is Button1... and if it is then create/show a new stage which uses sample.fxml as the resource. It then runs the final file, Loop.java
public class Controller implements Initializable {
public Stage loadingStage;
#FXML
ProgressIndicator progressIndicator;
public void handlerButtonClick() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("field.fxml"));
Parent rootOne = loader.load();
((Controller) loader.getController()).setPrimaryStage(primaryStage);
((Controller) loader.getController()).setPrimaryScene(scene);
sceneField = new Scene(rootOne, 420, 510);
primaryStage.setScene(sceneField);
primaryStage.setTitle("Import Data");
primaryStage.show();
}
public void fieldOption(ActionEvent e) throws Exception {
source = e.getSource();
if (source == Button1) {
Loop loopObj = new Main();
String[] args = {};
//Create new stage to contain the Progress Indicator
FXMLLoader loader2 = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root2 = loader2.load();
Controller2 controller = loader2.getController();
loadingStage = new Stage();
loadingStage.setTitle("Loading Stage");
Scene scene = new Scene(root2, 200, 200);
loadingStage.setScene(scene);
loadingStage.show();
//Runs the looper
loopObj.start(stage);
}
}
Sample.fxml
This code creates the Progress Indicator, and uses the controller Controller2
<AnchorPane prefHeight="200.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml/1"
xmlns="http://javafx.com/javafx/2.2" fx:controller="Controller2">
<children>
<ProgressIndicator fx:id="progressIndicator" layoutX="78.0" layoutY="55.0" progress="-1.0"/>
</children>
</AnchorPane>
Controller2.java
This code implements Initializable in order to make the Progress Indicator visible:
public class Controller2 implements Initializable {
#Override
public void initialize(URL url, ResourceBundle rb) {
ProgressIndicator progressIndicator = new ProgressIndicator();
progressIndicator.setVisible(true);
}
}
Loop.java
This is the main code that performs the loop. The loading stage should display the Progress Indicator until Loop.java calls its showMessage() function, at which point the loading stage closes. I know that it seems that one of these methods aren't necessary, but its only because they're stripped for demo purposes.
public class Loop extends Application {
#Override
public void start(Stage ignored) throws Exception {
Platform.setImplicitExit(false);
for (int i = 0; i <= 100; i++) {
if (i == 75){
saveAttachment("Hello");
}
}
}
public static void saveAttachment(String subject) throws IOException, MessagingException {
showMessage(subject);
}
private static void showMessage(String subject) throws IOException, MessagingException {
// Close the loading stage here.
}
}
Notice how it uses public void start(Stage ignored). Main.java uses public void start(Stage primaryStage). Perhaps this is bad.
I'm so frustrated please help!
UPDATE
I've applied Brian's suggestions, and within Controller.java have added a new task like so:
Stage loadingStage = new Stage();
//create task object
Task<Void> task = new Task<Void>(){
#Override
protected Void call() throws Exception{
System.out.println("Background task started...");
FXMLLoader loader2 = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root2 = loader2.load();
Controller2 controller = loader2.getController();
loadingStage.setTitle("Hello World");
Scene scene = new Scene(root2, 450, 250);
System.out.println("HERE6");
loadingStage.setScene(scene);
System.out.println("HERE7");
loadingStage.show();
System.out.println("HERE8");
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
System.out.println("Starting background task...");
th.start();
The problem now is that it doesn't reach the printout line saying "HERE7". It successfully enters the task and continues the main code, but the task doesn't get beyond where it prints "HERE6" therefore no new stage is opened. What gives?
In Ctlr2 you have ProgressIndicator progressIndicator = new ProgressIndicator(); but if it's in the FXML file you don't create a new one. Just do #FXML ProgressIndicator progressIndicator; like you have in the first Ctlr for some reason??
But this won't solve your problem, you're running everything on the JavaFX Application thread (GUI thread). What is probably happening (I didn't really read the code) is that you're doing both things on the same thread and the progress indicator has to wait for main to finish and then it can update the GUI. You put tags for task and concurrency, that's what you need.
Check here and do a search for more examples.
https://stackoverflow.com/a/22847734/2855515
I am new to JavaFX and trying to create an Confirmation Dialogbox.
I know already that there is no real build in dialogbox in JavaFX so I created one myself like this:
#FXML
public void delBox() {
try {
Stage dialogStage = new Stage();
AnchorPane root = FXMLLoader.load(getClass().getResource("Dialog.fxml"));
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();
} catch(Exception e) {
e.printStackTrace();
}
}
It looks pretty good already, but what I dont understand is, how those two Stages can communicate with each other? I want to pass a String to the dialog which is than shown in the message, also when one of the buttons in the dialog window is clicked I wanna react to this in the accordingly.
Can anyone explain me how communication between the stages works?
btw: I use .FXML files and controller classes.
You need a reference to the controller for the dialog. To do this, create an instance of FXMLLoader instead of using the static FXMLLoader.load(URL) method.
For example, suppose you have a class DialogController, so your Dialog.fxml looks like:
<AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml">
...
</AnchorPane>
Then you can access the DialogController in the delBox() method above with
Stage dialogStage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("Dialog.fxml"));
AnchorPane root = (AnchorPane)loader.load();
DialogController controller = (DialogController) loader.getController();
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();
And now you can communicate between the two controllers. For example, in DialogController you could define a message property, and bind it to a Label :
public class DialogController {
private final StringProperty message = new SimpleStringProperty("");
public void setMessage(String message) {
this.message.set(message);
}
public String getMessage() {
return message.get();
}
public StringProperty messageProperty() {
return message ;
}
#FXML
private Label label ;
public void initialize() {
label.textProperty().bind(message);
// ...
}
}
And then back in your delBox() method:
//... as before:
AnchorPane root = (AnchorPane)loader.load();
DialogController controller = (DialogController) loader.getController();
controller.setMessage("Hello World");
// ...
Similarly, you can define properties which are set when controls are pressed in the dialog itself, and either observe them or query them after the showAndWait() call.
There are a bunch of other similar techniques. Some examples:
https://github.com/james-d/Shared-Data-Controller/tree/master/src
https://github.com/james-d/Dialog-FXML-Example/tree/master/src
https://github.com/james-d/Nested-Controller-Example/tree/master/src/nestedcontrollerexample
<AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml">
...
</AnchorPane>
FX Controller is a java file, so it has to be DialogController and the Controller's path should be included i.e, fx:controller="applicationPackageName.DialogController"
The above mentioned fxml code does not work. It results in
javafx.fxml.LoadException
java.lang.InstantiationException
java.lang.NoSuchMethodException
Reason: The jvm looks for a class constructor with 0 parameters to build an instance. To overcome the error, the controller file needs to be loaded in the function coded in java:
loader.setController(new ControllerName(""));
To sum up (Working code):
FXML file:
<BorderPane id="background" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="320.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button onAction="#close" text="OK" />
</children>
</HBox>
</bottom>
<center>
<Label fx:id="messageLabel" />
</center>
</BorderPane>
Controller file:
public class PiPreferenceController {
private final String message ;
#FXML
private Label messageLabel ;
#FXML
void initialize() {
messageLabel.setText(message);
}
public PiPreferenceController(String message) {
this.message = message ;
}
#FXML
public void close() {
messageLabel.getScene().getWindow().hide();
}
}
Function:
void dialogPreferences() throws IOException {
Stage dialogStage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"PiPreference.fxml"));
loader.setController(new PiPreferenceController(""));
BorderPane root = (BorderPane) loader.load();
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();
}
i am using javafxml and swing in a single program. when i click a button on swing i need a text to be displayed in javafx panel. how to obtain fxml controller's object so that i can use it to update the changes in FX panel? Can any one help to solve this please ? Thanks in advance !
We have tried to access swing from FX where we succeeded. But the other part is not possible.
sample.java :
public void actionPerformed(java.awt.event.ActionEvent e)
{
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"FXMLDocument.fxml"
)
);
FXMLDocumentController controller =
loader.<FXMLDocumentController>getController();
controller.updatePage("hello boss");
}
FXMLDocument.fxml:
< GridPane fx:controller="com.comp.sweta.FXMLDocumentController" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
< /HBox>
< Text fx:id="actiontarget" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
< /GridPane>
FXMLDocumentController class:
public class FXMLDocumentController
{
#FXML public Text actiontarget;
public void updatePage(String data){
System.out.println("Testing phase");
this.actiontarget.setText(data);
}
}
we are getting NullPointerException. not able to set text in fxpanel this way.
I think you are missing a line between your first 2 statements in the actionPerformed method:
public void actionPerformed(java.awt.event.ActionEvent e)
{
FXMLLoader loader = ...;
Parent gridpane = (Parent) loader.load();
FXMLDocumentController controller = ....;
controller.updatePage("hello boss");
}