How to position controls binding there position into the stage's size using the controller class in JavaFx? - javafx-8

I found some thing similar in this link
How to call functions on the stage in JavaFX's controller file
and here is what I found in one of the answers
StageTrackingSample.java
public class StageTrackingSample extends Application {
#Override public void start(final Stage stage) throws Exception {
final FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"stagetracking.fxml"
)
);
final Parent root = (Parent) loader.load();
final StageTrackingController controller = loader.getController();
controller.initData(stage);
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
StageTrackingController.java
public class StageTrackingController {
#FXML private Label stageX;
public void initialize() {}
public void initData(final Stage stage) {
stageX.textProperty().bind(
Bindings.format(
"(%1$.2f, %2$.2f)",
stage.xProperty(),
stage.yProperty()
)
);
}
}
I wanted to position the progressIndicator in the middle of the window, so I tried this in my controller class
Controller.java
public void initInterface(Stage stage) {
progressIndicator.layoutXProperty().bind(stage.widthProperty().divide(2));
progressIndicator.layoutYProperty().bind(stage.heightProperty().divide(2));
}
and this in Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
final FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
final Parent root = loader.load();
final Controller controller = loader.getController();
final Scene scene = new Scene(root);
controller.initInterface(primaryStage);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
it doesn't work even when I tried passing the scene or the anchorpane(which is defined in the fxml file) as a parameter into initInterface method, it seems that it has problem with binding progressIndicator properties

by using the layoutXProperty and layoutYProperty and binding them to the Stage's width and height you must be trying to put it in the lower right hand corner of the stage. You can achieve this much easier, and JavaFX insists you do so, by using layouts in your scene and making the scene fill the entire area in question.
"From the Javadocs for the layoutX property:
If the node is managed and has a Region as its parent, then the layout region will set layoutX according to its own layout policy. If the node is unmanaged or parented by a Group, then the application may set layoutX directly to position it.
What this means is that the LayoutX/Y properties are controlled by the parent (and so it should be able to 'set' them). However, when you bind them they cannot be set anymore resulting in " A bound value cannot be set" exception."
Here is a good tutorial on regions and how to get things to layout in SceneBuilder as you please. If you're not using SceneBuilder I recommend it.
https://www.youtube.com/watch?v=zvgWgpGZVKc&list=PL6gx4Cwl9DGBzfXLWLSYVy8EbTdpGbUIG&index=35

Related

How is a non-static method accessed without an object?

I am new to JavaFX. In my following code, getHBox() is a non-static method is accessed without creating an object.
public class Main extends Application {
public void start(Stage primaryStage) {
//Main m = new Main();
try {
BorderPane rootPane = new BorderPane();
rootPane.setTop(getHBox());
//rootPane.setTop(m.getHBox());
Scene scene = new Scene(rootPane,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public HBox getHBox()
{
HBox hb = new HBox(15);
hb.getChildren().add(new Button("Press"));
return hb;
}
public static void main(String[] args) {
launch(args);
}
}
Now I have looked at the answers in Stackoverflow. Guys are talking something about class member. How is getHBox() method different from any other method? Please provide some explanation or direct me to an appropriate tutorial.
In my following code, getHBox() is a non-static method is accessed without creating an object.
That is incorrect. As used in the code presented, getHBox() is invoked only by start(), another non-static method. As an instance method itself, start() must be invoked on an object (one instantiated by JavaFX, for instance). The invocation of getHBox() without designating a target object is implicitly directed to the same object, as if it were this.getHBox().
How is getHBox() method different from any other method?
It isn't, not in any relevant sense, nor is any of this specific to JavaFX.

Read JavaFx Application

I created a small javaFx Program. The Program just displays random points. Now I want to get and read the generated Stage from a different class and read the co-ordinates. Is it possible ?
I tried creating a class variable to get stage but its null always.
I added a class variable and assigned the prepared Stage object to the variable. I am then trying to get the Stage object from the variable.
public class DCGUI extends Application {
private Stage primaryStage1;
public static void main(String[] args) {
launch(args);
Platform.exit();
}
#Override
public void start(Stage primaryStage) throws Exception {
Random r = new Random(64);
// List<Integer> points = r.ints(1000, 0, 400).boxed().collect(Collectors.toList());
List<Node> cList = new ArrayList<>();
Line line = null;
Circle c = null;
for (int i = 0; i < 50001; i++) {
//System.out.println(r.nextInt());
c = new Circle(r.nextInt(400), r.nextInt(400), 0.0125);
c.setStroke(Color.RED);
c.setId(i+"");
cList.add(c);
}
Group group = new Group(cList);
Scene scene = new Scene(group, 400, 400);
primaryStage.setScene(scene);
primaryStage.setTitle("Dynamic Connectivity");
primaryStage1 = primaryStage;
primaryStage.show();
}
Let's assume the following code example. By calling the getMainStage() method you can have access to your Stage object.
Of course, the main.fxml file is binded with the MainController class
Main.java
public class Main extends Application{
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader("path/to/main.fxml").toFile().toURI().toURL());
MainController.setMainStage(stage); <---- !
Parent root = loader.load();
stage.setScene(new Scene(root, 1400, 850));
stage.show();
}
public static void main(String[] args) {
launch(args);
}}
MainController.java
public class MainController{
// fxml view elements...
private static Stage mainStage;
//...
public static Stage getMainStage() {
return mainStage;
}
}

JavaFx Change main class to another main class (seperate class)

I'm new to JavaFx and have to create a small game. My JavaFx classes works fine but I can't figure out have to change between them. I created a package in eclipse where I have all the display classes (Menu screen class, lauding Screen class, Game display...). Every classes has their main and display fine. But now I can't change from one class to another class. Like from Start menu to game display. I tried initiating the game display class in the menu class and then setScene to game display's scene but it does not work. I'm also confused with either I have to change from stage, scenes or panes.
#Override
public void start(Stage primaryStage) throws Exception {
stage = primaryStage;
scene = new Scene(createContent());
primaryStage.setTitle("Menu Screen");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
2nd Class:
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Bucanneer");
// Setting up Stage, Scene and root
// Group root = new Group();
theScene = new Scene(createContent());
primaryStage.setScene(theScene);
primaryStage.setResizable(true);
primaryStage.show();
}
Last try:
I put this in the menu class when you press a button
private void backToMenu(){
Test test = new Test();
stage.setScene(test.getTheScene());
}
Any advice plz, all I can find are with FXML..
Ps: Sorry for bad english. Not my native language.

get scene from MenuItem

How i can get scene from MenuItem? i tried this code:
public class MainController implements Initializable {
#FXML
private MenuBar menuBar;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
public void show(ActionEvent event) throws IOException{
Parent root = FXMLLoader.load(getClass().getResource("FXML.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(menuBar.getScene().getWindow());
stage.show();
}
}
the above code does not generate an error, but it does not display the window!!!
Well, in your Controller class add a variable for Scene with the getters and setters.
Then you can do something like this:
#Override
public void start(Stage primaryStage)throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
Parent root = loader.load();
MainController mainControls = loader.getController();
Scene scene = new Scene(root, 300, 250);
mainControls.setScene(scene);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
Now the scene is available to all items in that class.
It looks like you're trying to create a Dialog of sorts?
If so don't use the Main scene... create a new Stage and show that with it's content...
Although I believe the JDK comes with Dialog support now.

JavaFX: How to update the center view of a borderpane with new values

I am creating a program which has a row of buttons on the top, and a row of buttons on the side.
The top buttons control the view, and the side buttons control what object to reference in the view.
My main/root view is a borderpane.
The point is to, as I click on any of these buttons, to change a value in my MainController, and then reload the center view with these new values. I thought it would be so simple as to write a method that would change the value and then set a new center according to these values.
However, as I test it, it can display the two values I have already asked it to display, but gives me a huge load of red error code whenever I run.
My MainViewController looks as follows:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainViewController extends Application {
#FXML
private Button cabin1;
#FXML
private Button cabin2;
#FXML
private Button tab1;
#FXML
private Button tab2;
#FXML
public void setCabinOne() throws IOException {
cabinIndex=1;
setCenterView();
}
#FXML
public void setCabinTwo() throws IOException {
cabinIndex=2;
setCenterView();
}
#FXML
public void setTabOne() throws IOException {
tabIndex=1;
setCenterView();
}
#FXML
public void setTabTwo() throws IOException {
tabIndex=2;
setCenterView();
}
public int getCabinIndex() {
return cabinIndex;
}
public int getTabIndex() {
return tabIndex;
}
private int tabIndex=0;
private int cabinIndex=1;
public Stage primaryStage;
private BorderPane mainPane;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage=primaryStage;
primaryStage.setTitle("Test");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainViewController.class.getResource("MainView.fxml"));
mainPane = loader.load();
setCenterView();
Scene scene = new Scene(mainPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public void setCenterView() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainViewController.class.getResource("TestView.fxml"));
AnchorPane testPane = loader.load();
TestViewController tvc = loader.<TestViewController>getController();
tvc.changeLabel(getCabinIndex());
tvc.changeIndex(getTabIndex());
mainPane.setCenter(testPane);
}
}
and my TestViewController looks as follows:
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class TestViewController {
#FXML
private Label cabinIndex;
#FXML
private Label tabIndex;
public void initialise() {
this.changeLabel(0);
this.changeIndex(0);
}
public void changeLabel(int n) {
cabinIndex.setText("Cabin "+Integer.toString(n));
}
public void changeIndex(int n) {
tabIndex.setText("Tab "+Integer.toString(n));
}
}
What am I doing wrong?
Your application is basically structurally wrong: you are using the application subclass as the controller, and this simply won't work (at least, not easily). You need to refactor this with a startup class (subclass of Application) that is distinct from the controller. Virtually any complete example will work as a template for you, but the Oracle tutorial is a good place to start.
What is happening is as follows:
When you call Application.launch() in MainViewController.main(...), the FX toolkit is started, an instance of your application class MainViewController is created, the FX Application Thread is started, and the start() method belonging to the MainViewController instance is invoked on the FX Application Thread.
When you call the FXMLLoader's load() method, it parses the FXML file at the specified location. When it sees the fx:controller attribute, which I'm assuming is fx:controller="MainViewController", it creates an instance of the specified controller class. Once the FXML is parsed, any matching #FXML-annotated fields (belonging to that instance) are initialized with the corresponding objects from the FXML file, and then the initialize() method is called on that instance.
So notice now you actually have two instances of MainViewController: the one from which FXMLLoader.load() was called, and the one created by the FXMLLoader. The #FXML-annotated fields in the instance created by the FXMLLoader are initialized, but the ones in the original instance remain set to the default value of null. Conversely, the mainPane field is initialized in the start method in the original MainViewController instance, but is never initialized in the instance created by the FXMLLoader. So when you press the button and invoke setCenterView() (I assume this is how your FXML is set up), you end up calling mainPane.setCenter() when mainPane is still null.
You could probably just about force it to work like this. Something like: remove the fx:controller attribute from MainView.fxml, and call loader.setController(this). But when you stray that far from the usual patterns used by a framework, your code becomes hard to maintain and debug. I would recommend following the design intended by the API.