I've been trying button events between 2 scenes in Javafx.
This is Start.fxml (in view package):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="292.0" prefWidth="383.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.StartController">
<children>
<Label fx:id="lbl1" layoutX="87.0" layoutY="60.0" prefHeight="17.0" prefWidth="209.0" />
<TextField fx:id="txt1" layoutX="87.0" layoutY="121.0" prefHeight="25.0" prefWidth="209.0" />
<Button fx:id="btn1" layoutX="171.0" layoutY="191.0" mnemonicParsing="false" onAction="#btn1Click" text="Click" />
</children>
</AnchorPane>
This is Preserences.fxml (in view package):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="292.0" prefWidth="383.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.PreferencesController">
<children>
<Label fx:id="lbl2" layoutX="87.0" layoutY="60.0" prefHeight="17.0" prefWidth="209.0" />
<TextField fx:id="txt2" layoutX="87.0" layoutY="121.0" prefHeight="25.0" prefWidth="209.0" />
<Button fx:id="btn2" layoutX="171.0" layoutY="191.0" mnemonicParsing="false" onAction="#btn2Click" text="Click" />
</children>
</AnchorPane>
This is Main.fxml which is like a container for the previous 2 files.(in view package):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="481.0" prefWidth="468.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.MainController">
<children>
<TabPane layoutX="14.0" layoutY="14.0" prefHeight="481.0" prefWidth="468.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab closable="false" text="Start">
<content>
<fx:include source="Start.fxml" />
</content>
</Tab>
<Tab closable="false" text="Preferences">
<content>
<fx:include source="Preferences.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
This is StartController.java (in controller package):
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class StartController implements Initializable {
#FXML public static Label lbl1;
#FXML public static TextField txt1;
#FXML public static Button btn1;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML private void btn1Click(ActionEvent e){
System.out.println("Button 1 clicked");
lbl1.setText(PreferencesController.txt2.getText());
}
}
This is PreferencesController.java (in controller package):
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class PreferencesController implements Initializable {
#FXML public static Label lbl2;
#FXML public static TextField txt2;
#FXML public static Button btn2;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML private void btn2Click(ActionEvent e){
System.out.println("Button 2 clicked");
lbl2.setText(StartController.txt1.getText());
}
}
This is MainController.java (in controller package):
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
public class MainController implements Initializable{
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
}
}
Finally, this is Main.java in application package:
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("/view/Main.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
But when I clicked the buttons, it gives me the errors:
"Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException...
...
Caused by: java.lang.NullPointerException
at controller.StartController.btn1Click(StartController.java:26)
... 61 more"
Please help me! :(
OK so the NPE is being thrown on this line:
lbl1.setText(PreferencesController.txt2.getText());
At the basic Java level, are only two ways that you could get that to happen:
when lnl1 is null, or
when PreferencesController.txt2 is null.
No other explanations are possible ... given that PreferencesController.txt2 is a static field.
I'm not familiar with JavaFX or FXML, but I suspect that your mistake is declaring the fields as static. I suspect that this causes the FXML mechanisms to not inject the reference to the UI component correctly. So those variables remain as null ... and you get an NPE.
Confirmation is here: https://stackoverflow.com/a/23109125/139985. (Thanks for the link #James_D)
Related
Using the FXML project template in netbeans, I've been experiencing an issue with defining the FX controller in my FXML file.
The main class, fxml document and fxml controller are all in the same package: "login".
I am importing the controller into the fxml document using it's fully qualified name.
Error occurs at the import line: "Class login.MyController does not exist."
FXML Document
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Polygon?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<?import login.MyController?>
<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="login.MyController">
<children>
<AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" style="-fx-background-color: #091D34;" VBox.vgrow="ALWAYS">
<children>
<Polygon fill="#000000b1" layoutX="363.0" layoutY="103.0" points="-50.0, 40.0, 50.0, 40.0, 50.0, -73.0" stroke="BLACK" strokeType="INSIDE" style="-fx-fill: #133863;" />
<ButtonBar layoutX="233.0" layoutY="256.0" prefHeight="40.0" prefWidth="161.0">
<buttons>
<Button layoutX="135.0" layoutY="18.0" minWidth="49.0" mnemonicParsing="false" prefHeight="25.0" text="Login" onAction="#doLogin" />
<Button layoutX="165.0" layoutY="18.0" mnemonicParsing="false" text="About" />
</buttons>
</ButtonBar>
<PasswordField layoutX="186.0" layoutY="216.0" prefHeight="25.0" prefWidth="273.0" promptText="Password" onKeyPressed="#onEnter" />
<TextField layoutX="186.0" layoutY="175.0" prefHeight="25.0" prefWidth="273.0" promptText="Username" />
<Text layoutX="253.0" layoutY="76.0" strokeType="OUTSIDE" strokeWidth="0.0" style="-fx-fill: #236AB9;" text="Anatomy Law" textAlignment="CENTER" wrappingWidth="120.58984375">
<font>
<Font name="Aparajita" size="22.0" />
</font>
</Text>
</children>
</AnchorPane>
Controller
package login;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public class MyController implements Initializable {
#FXML
public void doLogin(Event e){
System.out.println("do login called");
}
#FXML
public void onEnter(KeyEvent ke){
if(ke.getCode() == KeyCode.ENTER){
System.out.println("on enter called");
login();
}
}
private void login(){
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
}
Main
package login;
import java.net.URL;
import javafx.application.Application;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader();
MyController fxmlController = new MyController();
fxmlLoader.setController(fxmlController);
fxmlLoader.setLocation(new URL("C:/.../login/Login.fxml"));
VBox vbox = fxmlLoader.<VBox>load();
Scene scene = new Scene(vbox);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Note
I recently tried the following line in my FXML document:
<?import login.*?>
Which resulted in "package login does not exist."
And
<?import MyController?>
Which resulted in class does not exist.
So i'm assuming it's some kind of build path error but they're all in the same package. I even added the package that they're in to additional source packages to build from just to make sure but that didn't solve anything. My project layout is the following:
Project Name
Source Packages
login
Login.fxml
MyController.java
Main.java
I reviewed the other question postings for this problem but no one seemed to have this specific problem. If I did however miss someone's post with an identical answer, I will gladly take that reference.
You don't have to import it. You have to specify the full name of your controller class though.
In your case it is login.MyController so fx:controller="login.MyController".
Though you might have some other problems because I'm not having any issues when i put that import statement in the fxml. It just isn't necessary.
Make sure that the document you are editing is definitely the document in your package.
Somehow, in my case I was actually editing a document outside of the package with the same exact name. This is why it couldn't find the controller class when I tried to import it.
i have created a web view in javafx and loaded a webpage in it. The webpage contain and image which is generated randomly from the server. Once the page is loaded i try to run the javascript to get the url of the image and try to apply it to image viewer but the url makes another request to server for another image and it render different image but i want the same image which is loaded first on the webview. i do not want my web viewer should request to another image and render it.
First.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="com.jb.FirstController">
<children>
<SplitPane dividerPositions="0.3732638888888889" layoutX="10.0" layoutY="3.0" prefHeight="372.0" prefWidth="578.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<WebView fx:id="webview" layoutX="6.0" layoutY="10.0" prefHeight="346.0" prefWidth="200.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ImageView fx:id="imageview" fitHeight="311.0" fitWidth="256.0" layoutX="23.0" layoutY="23.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
FirstController.java
package com.jb;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.ImageViewBuilder;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
/**
* FXML Controller class
*
* #author admin
*/
public class FirstController implements Initializable {
#FXML
WebView webview;
#FXML
ImageView imageview;
private WebEngine webengine;
#Override
public void initialize(URL url, ResourceBundle rb) {
webengine = webview.getEngine();
//once the page is loaded this event occures
webengine.getLoadWorker().stateProperty().addListener((obs,oldValue,newValue) -> {
//if page loaded successfully
if(newValue==Worker.State.SUCCEEDED)
{
//executing script to get the image src from webview
String img=(String)webengine.getDocument().getElementById("addimage").getAttribute("src");
System.out.println("img:"+img);
//img variable has the value 'http://localhost:8080/WebApplication10/getNewAddImage'
//'getNewAddImage' is a servlet which accept get request
//this servlet gives a random image from backend
//setting the url in image view
imageview.setImage(new Image(img));
}
});
//requesting to index.jsp to load in webview
webengine.load("http://localhost:8080/WebApplication10/index.jsp");
}
}
Test.java
package com.jb;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author admin
*/
public class Test extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("First.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
i need to load the same image which is first loaded in the webview
i do not won't to request to new image
Any help would be appreciated
Thanks
I'm building a program with JavaFX and I have an Accordion ac injected #FXML and I have a button that creates a titled pane in the Accordion. The problem is that this button on click adds a titled pane to the accordion once.
I'm using this code:
t1.setContent(l);
ac.getPanes().add(t1);
I want to add one pane every click on this button. Please help me and thank you!
is this what you are looking for?
Scene.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="404.0" prefWidth="543.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pl.brocode.tg.magisterka.mavenproject1.FXMLController">
<children>
<Button fx:id="button" layoutX="193.0" layoutY="283.0" onAction="#handleButtonAction" text="Click Me!" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="193.0" AnchorPane.rightAnchor="193.0" />
<ScrollPane fitToHeight="true" fitToWidth="true" prefViewportHeight="160.0" prefViewportWidth="320.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<Accordion fx:id="accordion" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</content>
</ScrollPane>
</children>
</AnchorPane>
FXMLController
package test;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Accordion;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.AnchorPane;
public class FXMLController implements Initializable {
#FXML
private Accordion accordion;
#FXML
private void handleButtonAction(ActionEvent event) {
AnchorPane newPanelContent = new AnchorPane();
newPanelContent.getChildren().add(new Label("Hello World"));
TitledPane pane = new TitledPane("World Pane", newPanelContent);
System.out.println(accordion);
accordion.getPanes().add(pane);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
every time you click a button, new panel is added. if you wane do something with that panel in the future, you can assign it to field (list), or get it from accordion via getChildren() method.
an edit has been made to a code, for better display of added panes
Can Anybody tell me how to construct HiddenSidesPane in FXML not in the controller?
I am having the basic controller code for this but I am not able to understand how to create fxml structure from that.
Can I have something like this? Below code;
<HiddenSidesPane prefWidth="800.0" pinnedSide="TOP">
<content>
<HBox fillHeight="false" nodeOrientation="RIGHT_TO_LEFT"
prefHeight="27.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="3.0" StackPane.alignment="TOP_RIGHT">
<children>
<Label prefHeight="14.0" prefWidth="94.0" text="Value Date From">
<HBox.margin>
<Insets right="2.0" top="5.0" />
</HBox.margin>
</Label>
</children>
<StackPane.margin>
<Insets top="2.0" />
</StackPane.margin>
</HBox>
</content>
</HiddenSidesPane>
This how I made a fast example with the offical FXSampler of ControlsFX in mind:
Assumptions
You already set up your FXML Project and added the ControlsFX.jar as dependency on your build path.
FXMLDocument.fxml
Watch for the import statements.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import org.controlsfx.control.*?>
<StackPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="200" prefWidth="320" fx:controller="javafxapplication17.FXMLDocumentController">
<children>
<HiddenSidesPane fx:id="pane">
<content>
<Label alignment="CENTER" style="-fx-background-color: white; -fx-border-color: black;" maxHeight="1000.0" maxWidth="1000.0" text="Content Node" />
</content>
<top>
<Label fx:id="pinLabel" style="-fx-background-color: rgba(0,255,0,.25);" text="(Click to pin / unpin)" alignment="CENTER" prefHeight="50.0" prefWidth="50.0" onMouseClicked="#handleMouseClicked" />
</top>
</HiddenSidesPane>
</children>
</StackPane>
FXMLController.java
Inject your variables pane and pinLabel to set them.
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Side;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import org.controlsfx.control.HiddenSidesPane;
public class FXMLDocumentController implements Initializable {
#FXML
private HiddenSidesPane pane;
#FXML
private Label pinLabel;
#FXML
private void handleMouseClicked(MouseEvent event) {
if (pane.getPinnedSide() != null) {
pinLabel.setText("(unpinned)");
pane.setPinnedSide(null);
} else {
pinLabel.setText("(pinned)");
pane.setPinnedSide(Side.TOP);
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
JavaFXApplication17.java
Sorry for that name :-)
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class JavaFXApplication17 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
As far as you already know here is the JavaDoc of HiddenSidesPane: http://controlsfx.bitbucket.org/org/controlsfx/control/HiddenSidesPane.html
And if you need an example download the Zip http://fxexperience.com/downloads/controlsfx-8.40.9.zip and unzip it, there is a file controlsfx-samples-8.40.9.jar inside. Double click it and show the sources.
Ok so I've created my own customer label, for this example it's extremely basic. What I did was extend the Javafx Label in my custom class called MyLabel. I'm also using FXML to create the GUI. Now when I do this I can't seem to instantiate with my custom class as I get this error.
"Can not set net.blacksquirreldevs.tests.MyLabel field net.blacksquirreldevs.tests.SampleLabelController.sampleLabel to javafx.scene.control.Label"
Here is the code for everything
Main.java
package net.blacksquirreldevs.tests;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("SampleLabel");
AnchorPane anchorPane = (AnchorPane) FXMLLoader.load(getClass().getResource("SampleLabel.fxml"));
primaryStage.setScene(new Scene(anchorPane));
primaryStage.show();
}
public static void main(String... args) {
launch(args);
}
}
MyLabel.java
package net.blacksquirreldevs.tests;
import javafx.scene.control.Label;
public class MyLabel extends Label {
public MyLabel(String text) {
super();
setText(text);
}
}
SampleLabelController.java
package net.blacksquirreldevs.tests;
import javafx.fxml.FXML;
import java.net.URL;
import java.util.ResourceBundle;
public class SampleLabelController {
#FXML
private ResourceBundle resources;
#FXML
private URL location;
#FXML
private MyLabel sampleLabel = new MyLabel("Hello world!");
#FXML
void initialize() {
assert sampleLabel != null : "fx:id=\"sampleLabel\" was not injected: check your FXML file 'SampleLabel.fxml'.";
}
}
And finally the fxml file SampleLabel.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="net.blacksquirreldevs.tests.SampleLabelController">
<children>
<Label fx:id="sampleLabel" layoutX="153.0" layoutY="171.0" text="Sample Text">
<font>
<Font name="Arial Bold" size="50.0" />
</font>
</Label>
</children>
</AnchorPane>
So what I want to know is why I can' declare, in my SamplelabelController class, the sampleLabel as MyLabel?
Hopefully I've explained this well enough, if not let me know and I'll try to go a bit more in detail.
You are using <Label ... in your FXML instead of <MyLabel
Beside that your MyLabel has a none default constructor and in this case you NEED to provide a builder named MyLabelBuilder so that FXMLLoader can create an instance of MyLabel