JavaFX - Access FXML item from remote Java class - java

I am fairly new to JavaFX and SceneBuilder and currently working on a project using these, but I will try to translate my issue to an easier scenario:
Let's assume that:
I have used SceneBuilder to create a Label with fx:id -> some_label and a Button with fx:id -> new_object that will automatically be created in the FXMLDocument.fxml.
I created a new java class RemoteObject.java, each RemoteObject having:
int unique_id;
Button some_button = new Button("Remote button");
Inside the FXMLController.java I will have:
#FXML
public Label some_label;
#FXML
//this will be the handler for Button new_object
//which created using SceneBuilder
public void handleButtonAction(ActionEvent event)
{
<< create a new RemoteObject here >>
<< add RemoteObject.some_button to the scene >>
}
The main FooApp.java class would look like:
public class FooApp 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();
}
public static void main(String[] args) {
launch(args);
}
}
After running the program and pressing the new_object button, the result should look like:
The question is, how should the RemoteObject.some_button's handler be implemented in order to change some_label's caption (for example to RemoteObject.unique_id) on click?

Related

How to use JavaFX in Main

I am completly lost atm. I have been working with scenebuilder and javaFX in the past but I am stuck like 5 hours now and I didnt get a step further. Let me explain:
I have a working java Eclipse Project, using maven dependencies
The Main is where I want to use JavaFX or load a fxml into
The programm takes many many VCC Files and extracts the data to put it all together in an excel
The programm works but I cant load a FXML file into the main or even show a pane in there
Now does my Java Main class has to extend Application? I tried both ways - doenst work.
Some example code:
public void start(Stage primaryStage) {
try {
bpmain = new BorderPane(FXMLLoader.load(new File("src\\fxml\\UserInterface.fxml").toURI().toURL()));
primaryStage.setScene(new Scene(bpmain));
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
or this (from original Docs)
public void start(Stage stage) {
Circle circ = new Circle(40, 40, 30);
Group root = new Group(circ);
Scene scene = new Scene(root, 400, 300);
stage.setTitle("My JavaFX Application");
stage.setScene(scene);
stage.show();
}
but this start method is just not getting called... where do I put that?
What my Programm should look like is pretty simple actually. I want a small UI Windows that lets you pick a Folder where the VCC data lives in and a OK Button that basically should run the Main method.
So a TextField that when its picked a Path in the Main gets replaced (filepath) and just a simple OK Button that says: yeah run the main - because the main works perfectly it is just that I cant show that ui and I dont know how to really connect it to the Main.java
Any help is appreciated - Ty
Option 1
public class Launch extends Application {
public static Stage stage = null;
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Main.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
this.stage = stage;
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Option 2:
public class SidebarController implements Initializable {
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
void btnHome_OnMouseClicked(MouseEvent event) throws IOException {
BorderPane borderPane = (BorderPane) ((Node) event.getSource()).getScene().getRoot();
Parent sidebar = FXMLLoader.load(getClass().getResource("/fxml/ContentArea.fxml"));
borderPane.setCenter(sidebar);
}
}

Struggling to get JavaFx app working, objects stop existing?

So i'm working on a pet project, essentially a digitalisation of a do it yourself role playing adventure book.
I switched to using Scenebuilder because of the freedom it allows when crafting a GUI.
I'm having trouble binding the data to the screen. It seems the objects I am calling either stop existing or are not the ones i need.
I am using a SQLite database for my data, and that seems to work fine.
I am using Maven to import the things i need, this also seems to work fine however this requires me to use
public class DdAppLauncher {
public static void main(String[] args) {
DdApp2.main(args);
}
}
into ->
public class DdApp2 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/mainWindow.fxml"));
stage.setTitle("Deathtrap Dungeon");
stage.setScene(new Scene (root, 800,600));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This brings up the titlescreen that contains a start button which is handled by the following controller.
public class MainController {
LocationsPool loc;
Location currentLocation;
#FXML
private ListView<String> inventory;
#FXML
private Text locationDescription;
#FXML
private Text descrA;
#FXML
private Text descrB;
#FXML
private Text descrC;
#FXML
private Text descrD;
#FXML
private Text descrE;
#FXML
private Text descrF;
#FXML
public void startButtonClicked(ActionEvent event){
try {
System.out.println("Starting game");
Stage stage = (Stage) ((Node)event.getSource()).getScene().getWindow();
// Swap screen
Parent root = FXMLLoader.load(getClass().getResource("/fxml/gameWindow.fxml"));
stage.setScene(new Scene(root,800,600));
} catch (IOException e) {
e.printStackTrace();
}
//Setup
loc = new LocationsPool();
currentLocation = loc.getLocation(1);
System.out.println(currentLocation.getDescription());
locationDescription = new Text(currentLocation.getDescription());
System.out.println(locationDescription.getText());
System.out.println(locationDescription);
}
#FXML
public void handleButtonA(){
System.out.println(currentLocation==null);
}
}
Output on console ->
starting game
The clamour... (works)
The clamour... (works)
On button press ->
True
So it seems the app "forgets" fields when it runs? or is it the controller that stop existing and is remade?
Furthermore when trying to bind data to fields with fx:id, it doesn't seem to link those fields to anything until i press that button.
Am i structuring this all wrong? What am i not getting?
The final product should have the description loaded and all the choices loaded for that location.
Then on a selection should load up a new location and new choices so the text needs to be updated.
Thanks in advance.
Kev

Adding Event listener to mainScene in Javafx using fxml

I have an fxml that describes my gui. I want to change text of the gui and start a task on any key press anywhere.
FXML
<Text fx:id="barcodeText"/>
Controller
#FXML
Text barcodeText;
public void start(Stage primaryStage) throws IOException {
this.primaryStage=primaryStage;
Scene mainScene =new Scene(root);
primaryStage.setScene(mainScene);
primaryStage.setResizable(false);
primaryStage.show();
Parent root = FXMLLoader.load(getClass().getResource("/view/foo.fxml"));
mainScene.addEventHandler(KeyEvent.KEY_PRESSED,new KeyboardEventHandler(){
#Override
public void handle(KeyEvent event) {
barcodeText.setText("foo");
}
});
This gives me a NullPointerException(inside JavaFX Application Thread) for the barcodeText pointer when I fire the event.
Am I doing something wrong?
The examples I looked at were using this approach without fxml, do I have to use an annotation to define the handler? where would I put "onAction" for the scene in the fxml?
(Aside: it looks like you are trying to use the same class for the controller, and for the application. Don't do that.)
Define a method in the controller class for setting the barcode text:
public void setBarcodeText(String barcode) {
barcodeText.setText(barcode);
}
Then call that method from your handler:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/foo.fxml"));
Parent root = loader.load();
MyControllerClass controller = loader.getController();
Scene mainScene = new Scene(root);
mainScene.addEventHandler(KeyEvent.KEY_PRESSED, new KeyboardEventHandler(){
#Override
public void handle(KeyEvent event) {
controller.setBarcodeText("foo");
}
});
Obviously, replace MyControllerClass with the actual name of the controller class.

Injecting variables to the JavaFX thread

I'm trying to learn JavaFX and I'm having some trouble understanding how the JavaFX thread can interact with the rest of my application. I'm using JavaFX for the interface window but I have some other stuff running in the main thread.
I load my FXML from a file I've created with the Scene Builder and I've attached the open method to a MenuItem in Scene Builder.
I've tried having an instance variable in the Editor class and populating it in the constructor as well as the start method but it's always null in the open method. As far as I understand this is because the open method is called from the JavaFX thread. What is the best practice to solve this problem? This goes the other way to, what if I want to access a component if the JavaFX thread in my main thread?
public class Editor extends Application {
private Stage stage;
private FileChooser fileChooser;
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setTitle("Editx");
stage.setScene(new Scene(
FXMLLoader.load(this.getClass().getResource("./Editor.fxml")),
1280,
800));
stage.show();
this.fileChooser = new FileChooser();
this.fileChooser.getExtensionFilters().add(
new FileChooser.ExtensionFilter("OBJ", "*.obj"));
this.fileChooser.getExtensionFilters().add(
new FileChooser.ExtensionFilter("All Files", "*.*"));
}
#FXML
private void open() {
// Both this.fileChooser and this.stage is null here for example
File file = this.fileChooser.showOpenDialog(this.stage);
}
}

Fullscreen stage is not working properly in JavaFX 2.1?

The first stage that I load it always open properly as fullscreen.
stage.setFullScreen(true);
stage.setScene(login_scene);
But when I change to another FXML the applications stays fullscreen (no top toolbar.. ), but the actual view content gets resized on the prefWidth/prefHeight of the root AnchorPane from FXML (I can see the desktop in my bottom right corner :|), and I want it to be dynamic to my screen resolution.
Thanks.
#Later Edit:
So on the start method of my main Class I load a Scene (created from an FXML doc) and set it to the Stage (the start method param). I save this stage for later use.
When I press a button with the same stage I save previously I change the scene to another FXML document
#Screenshots:
http://tinypic.com/r/2079nqb/6 - 1st scene works normally - code from start override method of the main class
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
stage.setScene(new Scene(root));
stage.setFullScreen(true);
stage.show();
currentStage = stage;
}
http://tinypic.com/r/szfmgz/6 - after reloading the second scene - the code below from sample controller class
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
JavaFXApplication12.currentStage.setScene(new Scene(root));
}
I have no idea about the real cause but here are 2 quick workarounds.
In the handleButtonAction method:
1) Don't create new scene just replace its content
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
JavaFXApplication12.currentStage.getScene().setRoot(root);
}
2) If you really nead to create new scene then toggle fullscreen
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
JavaFXApplication12.currentStage.setScene(new Scene(root));
Platform.runLater(new Runnable() {
#Override
public void run() {
JavaFXApplication12.currentStage.setFullScreen(false);
JavaFXApplication12.currentStage.setFullScreen(true);
}
});
}
If I am right to know your concern then You should use your primary stage as static or you can make it available to other controller by making getters and setters. So to get same stage to load other fxmls you can set it to when you are loading a fxml and also make sure that do not create another scene. Because due to new scene you actual content resized.
So you can use this
In Main.java:
YourController objYourController = loader.getController();
objYourController.setDialogStage(primaryStage);
In YourController.java:
public void setMystage(Stage primaryStage) {
this.primaryStage= primaryStage;
}
//To load another FXML
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
primaryStage.getScene().setRoot(rootLayout);
Hope it will help you.

Categories

Resources