I have a program that uses one form to add and display an object. I can use the form to add an object fine but when I try to display the same object in the form after this, no text will appear. The object is definitely added correctly and I can print out all of the elements so nothing is null. I think the error is with my .setText() line. I have created a smaller version of the program that just tries to display text:
public class TestApp extends Application {
private Stage primaryStage;
#FXML public TextField txtField;
#FXML public TextArea txtArea;
#FXML public Button btnTest;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Change Solutions");
showWelcome();
}
public void showWelcome(){
try{
AnchorPane page = FXMLLoader.load(TestApp.class.getResource("testFXML.fxml"));
page.setStyle("-fx-background: #FFFFFF;");
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("Welcome to Change Solutions");
primaryStage.show();
}catch (IOException i)
{
Logger.getLogger(TestApp.class.getName()).log(Level.SEVERE, null, i);
}
}
public void addText(){
txtArea.setText("test");
txtField.setText("test");
showWelcome();
}
public void handleButton(ActionEvent actionEvent) {
addText();
}
}
FXML:
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="testpack.TestApp">
<children>
<AnchorPane layoutX="76.0" layoutY="70.0" prefHeight="243.0" prefWidth="309.0">
<children>
<TextField fx:id="txtField" layoutX="45.0" layoutY="40.0" promptText="TextField" AnchorPane.leftAnchor="45.0" AnchorPane.topAnchor="40.0" />
<TextArea fx:id="txtArea" layoutX="45.0" layoutY="81.0" prefHeight="138.0" prefWidth="149.0" promptText="TextArea" AnchorPane.leftAnchor="45.0" AnchorPane.topAnchor="81.0" />
<Button fx:id="btnTest" layoutX="217.0" layoutY="109.0" mnemonicParsing="false" onAction="#handleButton" text="Button" AnchorPane.bottomAnchor="109.0" AnchorPane.rightAnchor="40.0" />
</children>
</AnchorPane>
</children>
</AnchorPane>
The code, both here and in the actual program, compiles without errors.
I have see versions of this question before but none of the solutions work for me so I thought I would start a new thread.
Related
I need to load and display some images at runtime in javafx, I managed to load one of them up, I create the ImageView passing that image as param but then the image doesn't show up. I discovered that the image is clickable (it recognizes on mouse events) but I can't display it
The controller
public class fx extends Application {
#FXML
// The reference of inputText will be injected by the FXML loader
private TextField inputUsername;
#FXML
private TextField inputUrl;
#FXML
private ComboBox inputConnectionType;
#FXML
private ComboBox inputColour;
#FXML
private Button submit;
#FXML
private ImageView imageView;
#FXML
private AnchorPane anchor;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Image image = new Image("/AD_weapons_IT_0211.png");
imageView = new ImageView(image);
Parent root = FXMLLoader.load(getClass().getResource("/fxml/form.fxml"));
Scene scene = new Scene(root);
stage.setWidth(415);
stage.setHeight(200);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public void submit()
{
System.out.println(inputUsername.getText()+"\n");
System.out.println(inputColour.getValue().toString()+"\n");
System.out.println(inputConnectionType.getValue().toString()+"\n");
System.out.println(inputUrl.getText()+"\n");
}
public void press()
{
System.out.println("CLICKED");
}
}
The fxml file
<?xml version="1.0" encoding="UTF-8"?>
<?language JavaScript?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.image.Image?>
<TitledPane animated="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="untitled" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.172-ea" fx:controller="provaProj.fx">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<ImageView fx:id = "imageView" fitHeight="150.0" fitWidth="200.0" layoutX="199.0" layoutY="112.0" onMousePressed="#press" pickOnBounds="true" preserveRatio="false" />
</children></AnchorPane>
</content>
</TitledPane>
You should have 2 Classes and 1 fxml file for an FXML-Application:
Main Class:
public class TestApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLTest.fxml"));
stage.setTitle("Application");
Scene scene = new Scene(root);
stage.setWidth(415);
stage.setHeight(200);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
your fxml-File
and a Controller-Class:
public class Controller {
#FXML
// The reference of inputText will be injected by the FXML loader
private TextField inputUsername;
#FXML
private TextField inputUrl;
#FXML
private ComboBox inputConnectionType;
#FXML
private ComboBox inputColour;
#FXML
private Button submit;
#FXML
private ImageView imageView;
#FXML
private AnchorPane anchor;
public void submit()
{
System.out.println(inputUsername.getText()+"\n");
System.out.println(inputColour.getValue().toString()+"\n");
System.out.println(inputConnectionType.getValue().toString()+"\n");
System.out.println(inputUrl.getText()+"\n");
}
#FXML
public void press()
{
System.out.println("CLICKED");
Image img = new Image("yourURL");
imageView.setImage(img);
}
}
and you can then change your image in the Controller-Class..something like I made in the press method.
I would like to add a custom element into a VBox.
For example: being able to write VBox.getChildren().add(element) and element is a custom node created by me in FXML.
I already followed this tutorial: https://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
but the example only shows how to do this inside the same controller (a single controller, i already have my "big" controller, which is WinnerController, I would like to split the two classes, one that manages the single element, and one that manages the whole scene Winner.fxml).
I already have a class WinnerController which is the controller of my FXML Winner.fxml.
Here the code of my Winner.fxml:
<AnchorPane id="paneWinner" fx:id="paneWinner" prefHeight="800.0" prefWidth="1280.0" stylesheets="#winner.css" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.gui.WinnerController">
<children>
<VBox layoutX="434.0" layoutY="125.0" prefHeight="250.0" prefWidth="413.0" spacing="10.0">
<children>
<AnchorPane id="leaderBoardElement" prefHeight="80.0" prefWidth="413.0" stylesheets="#leaderBoard.css">
<children>
<Text layoutX="49.0" layoutY="45.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="107.13671875" />
</children></AnchorPane>
</children>
</VBox>
I would like to dynamically add element with the id "leaderBoardElement" (so an AnchorPane + Text) into my VBox.
How can i do that?
Edit: I also tried with this solution:How to understand and use `<fx:root>` , in JavaFX?
but i keep getting nothing. When i do vbox.getChildren().add(new MyComponent());
called in my WinnerControlleri get nothing.
WinnerController class:
public class WinnerController implements Initializable {
#FXML
private VBox leaderBoard;
#FXML
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Winner Init");
MyComponent test = new MyComponent();
System.out.println(test);
// leaderBoard.getChildren().add(new MyComponent());
}
}
My Component class:
public class MyComponent extends AnchorPane {
#FXML
private TextField textField ;
#FXML
private Button button ;
public MyComponent() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyComponent.fxml"));
loader.setController(this);
loader.setRoot(this);
loader.load();
textField.setText("HELLO!");
} catch (IOException exc) {
// handle exception
System.out.println("ELEMENT NOT CREATE!!!");
}
}
}
Winner.fxml:
<AnchorPane id="paneWinner" fx:id="paneWinner" prefHeight="800.0"
prefWidth="1280.0" stylesheets="#winner.css" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.gui.WinnerController">
<children>
<VBox fx:id="leaderBoard" layoutX="434.0" layoutY="125.0" prefHeight="250.0" prefWidth="413.0" spacing="10.0" />
MyComponent.fxml:
<fx:root type="javafx.scene.layout.AnchorPane" fx:id="leaderBoardElement" id="leaderBoardElement">
<TextField fx:id="textField" />
<Button fx:id="button" />
And i call the creation and loading of Winner.fxml from another class like this:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/Winner.fxml"));
if (loader!=null)
System.out.println("LOADER NOT NULL!!");
try{
System.out.println("TRY!");
Parent root = (Parent) loader.load();
if(root!=null)
System.out.println("ROOT NOT NULL!!");
Scene startedGame = new Scene(root, 1280, 800, Color.WHITE);
if(startedGame!=null)
System.out.println("SCENE NOT NULL!");
Stage window = (Stage) paneCarta0.getScene().getWindow();
if (window!=null)
System.out.println("WINDOW NOT NULL!!");
window.setScene(startedGame);
window.show();
catch (IOException Exception) {
System.out.println("View not found. Error while loading");
}
The problem is inside the new MyComponent(), where probably i get an exception and it propagates to my main caller. I've tried everything but i can't figure out why it can't create the MyComponent object.
If your custom component is in a separate FXML file you can do this.
In your WinnerController class:
#FXML
private void initialize() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getRessource("customElement.fxml"));
fxmlLoader.setController(new CustomElementController()); //Or just specify the Controller in the FXML file
myVBox.getChildren().add(fxmlLoader.load());
}
Edit: In this solution there should be NO <fx:include> tags in your main fxml
I want a Rectangle and a Label to align in the StackPane, however my code doesn't achieve the desired result:
FXML:
<fx:root type="HBox" xmlns:fx="http://javafx.com/fxml">
<StackPane fx:id="pane">
<children>
<Rectangle fx:id="bubble" fill="#ffffff"></Rectangle>
<Label fx:id="message" style="-fx-border-color:black; -fx-border-width: 1; -fx-border-style: solid;"></Label>
</children>
</StackPane>
</fx:root>
Controller:
public class MessageBubble extends HBox implements Initializable {
#FXML
private StackPane pane;
#FXML
private Label message;
#FXML
private Rectangle bubble;
#Override
public void initialize(URL location, ResourceBundle resources) {
message.setText("message");
pane.setAlignment(Pos.CENTER);
bubble.setArcWidth(15.0);
bubble.setArcHeight(15.0);
bubble.setStroke(Color.BLACK);
message.widthProperty().add(10.0).addListener((observable, oldValue, newValue) -> {
bubble.setWidth(newValue.doubleValue());
pane.layout();
});
message.heightProperty().add(10.0).addListener((observable, oldValue, newValue) -> {
bubble.setHeight(newValue.doubleValue());
pane.layout();
});
}
public MessageBubble() {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("MessageBubble.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Update
If I do sizing programmatically, it aligns fine:
this.pane.getChildren().addAll(this.bubble, this.message);
bubble.setFill(Color.ALICEBLUE);
bubble.setArcWidth(15.0);
bubble.setArcHeight(15.0);
bubble.setStroke(Color.BLACK);
message.setStyle("-fx-border-color:black; -fx-border-width: 1; -fx-border-style: solid;");
message.setText("message");
message.setPrefWidth(60.0);
message.setPrefHeight(25.0);
bubble.setWidth(70.0);
bubble.setHeight(30.0);
But this way, I need to calculate the size myself.
Basically, if you need a Text or Label with colored backround, the easiest approach to use CSS for a single Label or Text, without any Rectangle objects.
Example to use Label with CSS
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
HBox root = new HBox();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
Label message = new Label();
TextArea textArea = new TextArea();
textArea.setPrefWidth(200);
textArea.setText("message");
message.textProperty().bind(textArea.textProperty());
message.getStyleClass().add("rounded-background-label");
root.getChildren().addAll(message, textArea);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
application.css
.rounded-background-label {
-fx-background-color: black, white;
-fx-background-insets: 0, 1;
-fx-padding: 10px;
-fx-background-radius: 12px;
}
The answer from #jewelsea on this question is really detailed:
JavaFX 2: resizable rectangle containing text
But if you want to stay with the Label+Rectangle solution
I fear it is related to this bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8137252
As workaround you can request the layout update of the StackPane, as you have tried in the listeners.
The only problem with your code is that you should replace:
pane.layout();
with
Platform.runLater(new Runnable() {
#Override
public void run() {
pane.requestLayout();
}
});
which will ensure that the layout will happen on the GUI Thread.
Example
LabelRectangleTest.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.*?>
<HBox prefHeight="100.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.LabelRectangleTestController">
<children>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<StackPane fx:id="pane" minHeight="126.0" prefHeight="126.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
<children>
<Rectangle fx:id="bubble" arcHeight="15.0" arcWidth="15.0" fill="WHITE" height="27.75" stroke="BLACK" strokeType="INSIDE" width="68.0" />
<Label fx:id="message" text="Label" />
</children>
</StackPane>
<TextArea fx:id="textArea" prefWidth="200.0" wrapText="true" />
</children>
</HBox>
</children>
</HBox>
LabelRectangleTestController.java
public class LabelRectangleTestController implements Initializable {
#FXML
private Label message;
#FXML
private Rectangle bubble;
#FXML
private StackPane pane;
#FXML
private TextArea textArea;
#Override
public void initialize(URL location, ResourceBundle resources) {
textArea.setText("message");
message.textProperty().bind(textArea.textProperty());
message.widthProperty().addListener((observable, oldValue, newValue) -> {
bubble.setWidth(newValue.intValue() + 10);
Platform.runLater(new Runnable() {
#Override
public void run() {
pane.requestLayout();
}
});
});
message.heightProperty().addListener((observable, oldValue, newValue) -> {
bubble.setHeight(newValue.doubleValue() + 10);
Platform.runLater(new Runnable() {
#Override
public void run() {
pane.requestLayout();
}
});
});
}
}
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("LabelRectangleTest.fxml"));
HBox root = loader.load();
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Here is my Main java file.The probelm is that the Whole project is working on double click when i launch it.
public Stage primaryStage;
public BorderPane rootLayout;
private Pane splashLayout;
private ProgressBar loadProgress;
private Label progressText;
private static final int SPLASH_WIDTH = 600;
private static final int SPLASH_HEIGHT = 400;
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(final Stage initStage) throws Exception {
//this.primaryStage = primaryStage;
FXMLLoader fxmlLoader1 = new FXMLLoader(getClass().getResource(
"KDAF_Splash.fxml"));
try {
// flag = false;
Parent root2 = fxmlLoader1.load();
Stage stage2 = new Stage();
stage2.initStyle(StageStyle.TRANSPARENT);
// masterpane = new Pane();
// masterpane.setOpacity(1);
// stage2.setTitle("Create New Project");
stage2.setScene(new Scene(root2, 600, 400));
stage2.show();
PauseTransition delay = new PauseTransition(Duration.seconds(5));
delay.setOnFinished( event ->{ stage2.close();showMainStage();} );
delay.play();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
};
private void showMainStage(
) {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Preloader.class.getResource("RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Stage stage=new Stage();
stage.setTitle("Activation");
Scene scene = new Scene(rootLayout);
//stage.initStyle(StageStyle.DECORATED);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
showPersonOverview();
//mainStage.show();
/* mainStage.setTitle("Activation Wizard");
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
// primaryStage.initStyle(StageStyle.UTILITY);
mainStage.setResizable(false);
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setScene(scene);
mainStage.show();
showPersonOverview();*/
} catch (IOException e) {
e.printStackTrace();
}
}
public void showPersonOverview() {
try {
// Load person overview.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("activation wizard.fxml"));
AnchorPane personOverview = (AnchorPane) loader.load();
personOverview.setPrefHeight(400);
// Set person overview into the center of root layout.
rootLayout.setCenter(personOverview);
} catch (IOException e) {
e.printStackTrace();
}
}
private void showSplash(
final Stage initStage,
Task<?> task,
InitCompletionHandler initCompletionHandler
) {
progressText.textProperty().bind(task.messageProperty());
loadProgress.progressProperty().bind(task.progressProperty());
task.stateProperty().addListener((observableValue, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
loadProgress.progressProperty().unbind();
loadProgress.setProgress(1);
initStage.toFront();
FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2), splashLayout);
fadeSplash.setFromValue(1.0);
fadeSplash.setToValue(0.0);
fadeSplash.setOnFinished(actionEvent -> initStage.hide());
fadeSplash.play();
initCompletionHandler.complete();
} // todo add code to gracefully handle other task states.
});
Scene splashScene = new Scene(splashLayout);
initStage.initStyle(StageStyle.UNDECORATED);
final Rectangle2D bounds = Screen.getPrimary().getBounds();
initStage.setScene(splashScene);
initStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
initStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);
initStage.show();
}
public interface InitCompletionHandler {
public void complete();
}
}
The FXml is given below. Please help me to resolve this issue. If the question is not clear help me to explain better. The main problem is when the application is launched after splash screen. The button accepts double click and then moves to load next FXML. this is been very painful as i have to double click everytime instead of single click. I am not able to identify the problem here. Whether it is a problem that persists from scene builder or the problem is in the main preloader class.Even the menu item is accepting double click. I try to google the solution for but could not find any solution. please look int the code and help to resolve this issue. I have done a lot of R&D but all went vain . There might be a little problem in it but i am not being able to identify it. Please ignore the formatting of code and unused variables. The code is not final yet. finally i would like to remind the main problem is that after launching, the application is working only on double click. lets look at the work flow to understand it better. SPLASH SCREEN->ACTIVATION WIZARD-DOUBLE CLICK ON A BUTTON->TIP SCREEN-DOUBLE CLICK ON A BUTTON->PROJECT SCREEN->DOUBLE CLICK TO OPEN ANYTHING. It is really frustrating. please help.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-border-color: black;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="EventHandlingController">
<children>
<Button layoutX="301.0" layoutY="333.0" mnemonicParsing="false" text="Buy Full Version" />
<Button fx:id="myButton7" layoutX="420.0" layoutY="333.0" mnemonicParsing="false" onAction="#Showtip" prefHeight="25.0" prefWidth="114.0" text="Continue Trial " />
<TextField editable="false" layoutX="85.0" layoutY="108.0" prefHeight="151.0" prefWidth="449.0" style="-fx-background-color: silver;" text="You have <xx> days left on your trial.">
<font>
<Font size="21.0" />
</font>
</TextField>
<Label layoutX="85.0" layoutY="23.0" prefHeight="37.0" prefWidth="135.0" text="Activation Wizard">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Button fx:id="closebutt" layoutX="573.0" layoutY="2.0" mnemonicParsing="false" onAction="#closebuttonD" prefHeight="15.0" prefWidth="20.0" text="X" />
</children>
</AnchorPane>
I generated the following FXML in Scene Builder. When I preview it in Scene Builder and resize the window the inner split view maintains the spacing between itself and the anchor view. However when I run the FXML in my application it does not. Any ideas? I am using javafx 2.2.51.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="477.0" prefWidth="515.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.nm.haze.LibraryViewController">
<children>
<SplitPane dividerPositions="0.09484536082474226" focusTraversable="true" prefHeight="415.0" prefWidth="487.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="48.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView prefHeight="371.0" prefWidth="425.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
And my controller code:
package com.nm.haze;
import java.net.URL;
import java.util.ResourceBundle;
public class LibraryViewController extends BaseController {
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}
Main code
private static final String LIBRARY_SELECT = "LibrarySelect";
private static final String LIBRARY_VIEW = "LibraryView";
#Override
public void start(Stage primaryStage) throws IOException {
SceneController sceneController = new SceneController(primaryStage, new SettingsManager());
sceneController.loadScene(LIBRARY_SELECT);
sceneController.loadScene(LIBRARY_VIEW);
if (sceneController.setupNeeded()) {
sceneController.setScreen(LIBRARY_SELECT);
} else {
sceneController.setScreen(LIBRARY_VIEW);
}
Group root = new Group();
root.getChildren().addAll(sceneController);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
SceneController code:
public class SceneController extends StackPane {
Map<String, Node> scenes = new HashMap<>();
Stage stage;
SettingsManager settingsManager;
public SceneController(Stage stage, SettingsManager settingsManager) {
this.stage = stage;
this.settingsManager = settingsManager;
}
public void addScene(String name, Node scene) {
scenes.put(name, scene);
}
public void loadScene(String name) throws IOException {
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(name + ".fxml"));
Parent loadScreen = (Parent)myLoader.load();
((BaseController)myLoader.getController()).setSceneController(this);
addScene(name, loadScreen);
}
public void setScreen(final String name) {
List<Node> children = getChildren();
Node scene = scenes.get(name);
if(scene != null) {
if (children.size() > 0) {
children.remove(0);
}
children.add(0, scene);
} else {
throw new IllegalArgumentException("Scene has not been loaded");
}
}
public Stage getStage() {
return stage;
}
public boolean setupNeeded() {
return settingsManager.setupNeeded();
}
}
Just to be clear about what the issue is, please see the before and after screenshots below. The distance between the ListView and the AnchorPane should stay the same (and does in Scene Builder).
`You just have to fix the minimum and maximum width of the part of the SplitPane, whose width you dont want to change on resizing your window !
Here I have fixed the left part, by setting the minWidth and maxWidth of AnchorPane on the left side. You can do the same for the right side as well, depending on your requirement.
abcFxml.fxml
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="477.0" prefWidth="515.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="bounty.LibraryViewController">
<children>
<SplitPane dividerPositions="0.09484536082474226" focusTraversable="true" prefHeight="415.0" prefWidth="487.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="48.0">
<items>
<AnchorPane minHeight="0.0" minWidth="100.0" prefHeight="160.0" prefWidth="100.0" maxHeight="160.0" maxWidth="100.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView prefHeight="371.0" prefWidth="425.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
Controller
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class LibraryViewController extends Application
{
#Override
public void start(Stage arg0) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("abcFxml.fxml"));
AnchorPane pane = (AnchorPane) fxmlLoader.load();
Scene scene = new Scene(pane);
arg0.setScene(scene);
arg0.show();
}
public static void main(String args[])
{
launch(args);
}
}
Screenshots
Size1
Size 2
EDIT : As per user updation
The problem you are facing is because of the Group you are using. Group itself is not resizable ! Try to put the StackPane directly to your scene(like I did) or you can use any other container like VBOX / HBOX etc
#Override
public void start(Stage primaryStage) throws IOException {
SceneController sceneController = new SceneController(primaryStage, new SettingsManager());
sceneController.loadScene(LIBRARY_SELECT);
sceneController.loadScene(LIBRARY_VIEW);
if (sceneController.setupNeeded()) {
sceneController.setScreen(LIBRARY_SELECT);
} else {
sceneController.setScreen(LIBRARY_VIEW);
}
primaryStage.setScene(new Scene(sceneController));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}