My program is refusing to run because the "anchorpane" is refusing to support my controller on all my fxml files, hence my fxml page is not loading. Also, it is also giving me error message that my main class could not be found. I would welcome any help or suggestion on the stated.
My fxml file
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" pickOnBounds="false" prefHeight="614.0" prefWidth="1015.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="winnaccs.WinSecHomeController">
The Controller
public class WinSecHomeController implements Initializable, ControlledScreen {
ScreensController myController;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
public void setScreenParent (ScreensController screenParent){
myController = screenParent;
}
#FXML
private void goToLogin(ActionEvent event) {
myController.setScreen(Winnaccs.screen2);
}
}
just try to change this one
fx:controller="winnaccs.WinSecHomeController"
with this other
fx:controller="winnaccs/WinSecHomeController"
Related
Created custom design using FXML with two files CustomToggleSwitch.fxml and CustomToggleSwitch.java.
CustomToggleSwitch.fxml has following code
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<fx:root type="Pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button mnemonicParsing="false" onAction="#click" text="Button" />
</children>
</fx:root>
CustomToggleSwitch.java has code
package com.custom;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.Pane;
public class CustomToggleSwitch extends Pane{
int tick;
public CustomToggleSwitch() {
FXMLLoader loader=new FXMLLoader(getClass().getResource("CustomToggleSwitch.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
#FXML
public void click(ActionEvent actionEvent){
System.out.println(tick++);
}
}
Created jar file from these and used this jar file inside application project. Application has test.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import com.custom.*?>
<?import com.custom.CustomToggleSwitch?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane 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">
<children>
<CustomToggleSwitch layoutX="29.0" layoutY="48.0" />
</children>
</AnchorPane>
Controller class(TestController.java) has following
public class TestController implements Initializable{
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
}
#FXML
public void click(){
System.out.println("Test");
}
}
Button is shown successfully on GUI and Button click is also get detected.Button is showing 0,1,2,3..etc on output console. But Test is not getting printed on screen.
How can i detect button press in application controller class? Can someone help me to resolve this issue.
Thanks a lot to all.
add listener property with getter and setter in your component
controller.
The example of Jai is correct, but inconsistent with the other components of javafx. For proper implementation, it is appropriate to use properties that can be manipulated in both FXML and manual mode.
This is the user component controller that has an onMyAction property added. This property is used for event notification.
public class CustomToggleSwitch extends Pane {
private ObjectProperty<EventHandler<ActionEvent>> onMyAction = new SimpleObjectProperty<EventHandler<ActionEvent>>();
public CustomToggleSwitch() {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/sample/CustomToggleSwitch.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
}
catch (IOException e) {
e.printStackTrace();
}
}
#FXML
private void initialize() {
}
#FXML
private void click(ActionEvent event) {
if(onMyAction.get() != null) {
onMyAction.get().handle(event);
}
}
public EventHandler<ActionEvent> getOnMyAction() {
return onMyAction.get();
}
public ObjectProperty<EventHandler<ActionEvent>> onMyActionProperty() {
return onMyAction;
}
public void setOnMyAction(EventHandler<ActionEvent> onMyAction) {
this.onMyAction.set(onMyAction);
}
}
With such a structured component, the onMyAction property can be added by FXML for example
<AnchorPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" >
<CustomToggleSwitch onMyAction="#testHandler"/>
</AnchorPane>
public class Controller {
#FXML
private void testHandler(ActionEvent event) {
}
}
or manually
<AnchorPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" >
<CustomToggleSwitch fx:id="customToggleSwitch"/>
</AnchorPane>
public class Controller {
#FXML
private CustomToggleSwitch customToggleSwitch;
#FXML
private void initialize() {
customToggleSwitch.setOnMyAction(event -> {
});
}
}
Update
You don't need to use a property. Making the getter and setter available should be sufficient to use it from fxml. (I didn't encountered a case where I would add a listerner to a event handler property yet.)
This is a conversion without the use of Property
public class CustomToggleSwitch extends Pane {
private EventHandler<ActionEvent> myEventHandler;
public CustomToggleSwitch() {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/sample/CustomToggleSwitch.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
}
catch (IOException e) {
e.printStackTrace();
}
}
#FXML
private void initialize() {
}
#FXML
private void click(ActionEvent event) {
if(myEventHandler != null) {
myEventHandler.handle(event);
}
}
public EventHandler<ActionEvent> getOnMyAction() {
return myEventHandler;
}
public void setOnMyAction(EventHandler<ActionEvent> onMyAction) {
myEventHandler = onMyAction;
}
}
This is happening because onAction="#click" is declared in CustomToggleSwitch.fxml, so FXMLLoader will look for the click() in CustomToggleSwitch.java.
Adding a click() in TestController class is not going to do anything, because you do not have any node with onAction="#click" in test.fxml.
One way for the Button in CustomToggleSwitch to communicate with TestController class is to relay the event out.
public class CustomToggleSwitch extends Pane {
// Same stuff
private List<Runnable> onClickRunnables = new ArrayList<>();
public final void addButtonOnClickRunnable(Runnable runnable) {
Objects.requireNonNull(runnable);
onClickRunnables.add(runnable);
}
#FXML
private void click(ActionEvent actionEvent){
System.out.println(tick++);
if (!onClickRunnables.isEmpty()) {
onClickRunnables.forEach(r -> r.run());
}
}
}
public class TestController implements Initializable {
// Give CustomToggleSwitch control an fx:id in FXML
#FXML private CustomToggleSwitch customSwitch;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
customSwitch.addButtonOnClickRunnable(this::click);
}
}
Another way is to expose the Button in CustomToggleSwitch out. Personally, I would suggest against this because it's neater to keep implementation of a "control" hidden.
How i can do button action for editing TableView. I need to put text from TextArea to table when i touch button. And if put System.out.println in inputToTable() it is work.
public class InputController {
public TextArea inputArea;
public Button inputButton;
private TableController tableController;
public void initialize() {
tableControllerInit();
}
public void inputToTable() {
if(inputArea.getText() != "") {
tableController.tableInfo.setItems(FXCollections.observableArrayList(new InputObject(inputArea.getText())));
}
}
private void tableControllerInit() {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("table.fxml"));
fxmlLoader.load();
tableController = fxmlLoader.getController();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TableController {
#FXML TableView<InputObject> tableInfo;
#FXML TableColumn<InputObject, String> col1;
public void initialize() {
col1.setCellValueFactory(new PropertyValueFactory<>("text"));
}
}
public class Controller implements Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
}
}
public class InputObject {
String text;
public InputObject(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
<BorderPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<left>
<fx:include source="table.fxml"/>
</left>
<center>
<fx:include source="input.fxml"/>
</center>
</BorderPane>
<TableView fx:controller="sample.TableController" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:id="tableInfo" prefHeight="400.0" prefWidth="330.0">
<columns>
<TableColumn fx:id="col1" prefWidth="75.0" text="Output" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
<VBox fx:controller="sample.InputController" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
<children>
<TextArea fx:id="inputArea" prefHeight="188.0" prefWidth="270.0" />
<Button fx:id="inputButton" onAction="#inputToTable" mnemonicParsing="false" text="Input">
<VBox.margin>
<Insets bottom="30.0" left="30.0" right="30.0" top="30.0" />
</VBox.margin>
</Button>
</children>
</VBox>
You load table.fxml twice: once via the fx:include in the main FXML file, and once in InputController, via the FXMLLoader you create in the tableControllerInit() method. Consequently, two instances of TableController are created, one associated with the first UI you load from table.fxml, and one associated with the second UI you load from table.fxml.
The UI you load via the fx:include is displayed in the VBox defined in the main FXML file. The UI you load with the FXMLLoader is never displayed (in fact, you never even keep a reference to it, you just call loader.load() and discard the result). When you try to update the table's items (do you really intend to replace all the existing items, by the way?), you refer to the second controller instance, which is associated with the UI which is never displayed. Consequently, you are updating a table that is not displayed, and you never see any results.
What you really need to do is share the same data between the two controllers associated with the two fx:includes. You can do this simply by injecting those two controllers into the main controller, as described in the "Nested Controllers" section in the documentation.
First, give the fx:include elements fx:id attributes:
<BorderPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<left>
<fx:include fx:id="table" source="table.fxml"/>
</left>
<center>
<fx:include fx:id="input" source="input.fxml"/>
</center>
</BorderPane>
Then you can inject the controllers into the main controller by creating fields with the word "Controller" appended to the fx:id. Create a single observable list, which will represent the list of items displayed in the table, and pass it to each controller:
public class Controller implements Initializable {
#FXML
private TableController tableController ;
#FXML
private InputController inputController ;
#Override
public void initialize(URL location, ResourceBundle resources) {
ObservableList<InputObject> items = FXCollections.observableArrayList();
tableController.setTableItems(items);
inputController.setTableItems(items);
}
}
Finally, just define the obvious methods in each of the other two controllers:
public class TableController {
#FXML
private TableView<InputObject> tableInfo;
#FXML
private TableColumn<InputObject, String> col1;
public void initialize() {
col1.setCellValueFactory(new PropertyValueFactory<>("text"));
}
public void setTableItems(ObservableList<InputObject> tableItems) {
tableInfo.setItems(tableItems);
}
}
Now the table is displaying the contents of the items list created in the main controller's initalize() method, and the InputController has a reference to the same list. So all you need to do is update that list in the InputController. I assume you just want to add items to the table (not replace them all):
public class InputController {
#FXML
private TextArea inputArea;
#FXML
private Button inputButton;
private ObservableList<InputObject> tableItems ;
public void setTableItems(ObservableList<InputObject> tableItems) {
this.tableItems = tableItems ;
}
public void inputToTable() {
if(! inputArea.getText().isEmpty()) {
tableItems.add(new InputObject(inputArea.getText()));
}
}
}
More generally, if you have more data to share among the different controllers, you would create one or more "model" classes and share a model instance with the controllers. Then you can observe the properties of the model and update them. See Applying MVC With JavaFx for a more comprehensive example.
This question already has answers here:
JavaFX FXML controller - constructor vs initialize method
(3 answers)
Closed 6 years ago.
This is likely pilot error, but the FXML attribute is not binding to the controller class on fx:id. I've whittled it down to a trivial example, but still "no joy". What am I overlooking?
FXML file...
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:id="mainFrame" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.controller.BorderPaneCtrl">
<left>
<AnchorPane fx:id="anchorPaneLeft" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</left>
</BorderPane>
The associated Java code is...
package sample.controller;
import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;
public class BorderPaneCtrl {
#FXML private AnchorPane anchorPaneLeft;
public BorderPaneCtrl() {
/* so, #FXML-annotated variables are accessible, but not
* yet populated
*/
if (anchorPaneLeft == null) {
System.out.println("anchorPaneLeft is null");
}
}
/* this is what was missing...added for "completeness"
*/
#FXML
public void initialize() {
/* anchorPaneLeft has now been populated, so it's now
* usable
*/
if (anchorPaneLeft != null) {
// do cool stuff
}
}
Ego is not an issue here, I'm pretty sure I'm overlooking something simple.
FXML elements are not assigned yet in constuctor, but you can use Initializable interface where elements are already assigned.
public class Controller implements Initializable {
#FXML
AnchorPane anchorPaneLeft;
public Controller() {
System.out.println(anchorPaneLeft); //null
}
#Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println(anchorPaneLeft); //AnchorPane
}
}
I assume that you know that you should create controllers with FXML by using for example: FXMLLoader.load(getClass().getResource("sample.fxml");
Im trying to embed a video in a website to a mediaview of a simple javafx application. Ive got a sample code which I used as my javafx code. It opens the scene and plays the audio but wont play the video. How can I make it play the audio? Im using netbeans IDE 8.0.2,JavaFx 8 and scene builder 2.0
The Code ive tried is below.
Thanx in advanced.
#FXML MediaView mdv;
Media media;
public static MediaPlayer mpl;
#Override
public void initialize(URL url, ResourceBundle rb) {
media=new Media("http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv");
mpl=new MediaPlayer(media);
mpl.setAutoPlay(true);
mdv=new MediaView(mpl);
mpl.play();
mpl.setOnError(new Runnable() {
#Override public void run() {
System.out.println("Current Error: " + mpl.getError());
}
});
}
This is how I load the children to the stage
public class Production extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Vdo.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);
}
the FXML Ive got after creating the GUI from scene builder is below
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.media.*?>
<?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="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="production.VdoController">
<children>
<MediaView fx:id="mdv" fitHeight="300.0" fitWidth="300.0" layoutX="125.0" layoutY="85.0" />
<Button layoutX="235.0" layoutY="51.0" mnemonicParsing="false" text="Button" />
</children>
</AnchorPane>
You are re-initializing the MediaView that has been initialized by the FXMLoader. Never do this, because you will loose the reference to the original node.
You should just set the MediaPlayer to the MediaView instead of re-initializing it by using the setMediaPlayer().
#Override
public void initialize(URL url, ResourceBundle rb) {
media=new Media("http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv");
mpl=new MediaPlayer(media);
mpl.setAutoPlay(true);
mdv.setMediaPlayer(mpl);
mpl.play();
}
In my Java Fx application I create a two stages. The first stage is the default in the main controller class, HomeController. The second, AddNewEmailController, is created by calling a method, showNewComposeNewEmail(), in the AddNewEmailController class.
The new stage gets created fine, but none of the methods I try to call, like closing the AddNewEmailController stage, will work on the AddNewEmailController stage.
How can I get the methods to work?
I'd also like to have the HomeController stage inaccessible once the AddNewEmailController stage gets open, like how pop-up windows do.
I can't even get the AddNewEmailController stage to iconify?
Thank you all in advance.
The HomeController class:
public class HomeController implements Initializable {
// Initializes the controller class.
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
public void windowClose() {
Platform.exit();
}
#FXML
public void showNewComposeNewEmail() throws Exception {
new AddNewEmailController().newnewcomposeNewEmailStage();
}
}
The AddNewEmailController class:
public class AddNewEmailController implements Initializable {
public void setScreenParent(ScreensController screenParent) {
myController = screenParent;
}
// Initializes the controller class.
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
public Stage newComposeNewEmail;
public void newnewcomposeNewEmailStage() throws IOException {
newComposeNewEmail = new Stage();
newComposeNewEmail.initStyle(StageStyle.UNDECORATED);
newComposeNewEmail.initStyle(StageStyle.TRANSPARENT);
Parent newComposeNewEmailRoot = FXMLLoader.load(getClass().getResource("/wakiliproject/Forms/AddNew/NewEmail/NewEmail.fxml"));
StageDraggable.stageDraggable(newComposeNewEmailRoot, newComposeNewEmail);
Scene newComposeNewEmailScene = new Scene(newComposeNewEmailRoot, 590, 670);
newComposeNewEmail.setScene(newComposeNewEmailScene);
newComposeNewEmail.show();
}
#FXML
private void newComposeNewEmailClose() {
newComposeNewEmail.close();
}
#FXML
private void newComposeNewEmailIconify() {
newComposeNewEmail.setIconified(true);
}
}
UPDATE:
The NewEmail 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="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="wakiliproject.Forms.AddNew.NewEmail.TryEMailController">
<children>
<Label layoutX="190.0" layoutY="61.0" onMouseClicked="#newComposeNewEmailStageIconify" text="Minimise Window" />
<Label layoutX="300.0" layoutY="61.0" onMouseClicked="#newComposeNewEmailStageClose" text="Close Window" />
</children>
</AnchorPane>
In your fxml, your controller is
fx:controller="wakiliproject.Forms.AddNew.NewEmail.TryEMailController"
while in your code, the class name is
AddNewEmailController
Please make them same and recheck, your method will be called.
For making the new Stage as child of the Parent, please use
newStage.initModality(Modality.WINDOW_MODAL);
newStage.initOwner(PrimaryStage);