I am creating an app that has a main BorderPane with a menubar in the TOP. I want to change the CENTER content when a specific menu option is selected. However, when I do this, the AnchorPane that I load into the CENTER pane is not resizing to fill the CENTER pane. It keeps it's preferred size. I have tried setting it to USE_COMPUTED_SIZE, but that does not resize it to fill the CENTER pane. I also tried to add an HBOX as a wrapper around the AnchorPane (I am fairly new to JavaFX UI design) which also did not work.
<BorderPane id="BorderPane" prefHeight="650.0" prefWidth="980.0"
xmlns="http://javafx.com/javafx/8.0.60"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="fileinventory.ApplicationFrameController">
<top><MenuBar BorderPane.alignment="CENTER">...</MenuBar></top>
<center><AnchorPane BorderPane.alignment="CENTER" /></center>
</BorderPane>
I load the pane to set in the CENTER using the following call from the main class:
public void viewClients() {
ViewClientsController dlg =
new ViewClientsController(this.bundle, this.rootLayout);
}
And the actual controller for the AnchorPane being loaded to the CENTER pane.
public class ViewClientsController {
public ViewClientsController(ResourceBundle bundle, BorderPane layout) {
FXMLLoader fxmlLoader =
new FXMLLoader(getClass().getResource("ViewClients.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setResources(bundle);
try {
layout.setCenter(new AnchorPane((Parent) fxmlLoader.load()));
} catch (Exception ignore) {}
I do not know a lot about JavaFX layouts. I am more of a backend guy, so I am at a bit of a loss here.
Related
I have three layers
Root layout, home, content (rootLayout.fxml, home.fxml and content.fxml)
FXMLLoader loader = new FXMLLoader();
loader.setLocation(GenerateReport.class
.getResource("/skin/rootLayout.fxml"));
rootLayout = (AnchorPane) loader.load();
Scene scene = new Scene(rootLayout);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(GenerateReport.class
.getResource("/skin/home.fxml"));
AnchorPane homeLayout = (AnchorPane) loader.load();
rootLayout.getChildren().addAll(homeLayout);
.
.
.
rootLayout.getChildren().addAll(contentLayout);
like this I am adding content layout. In rootLayout.fxml i have a home button. My requiredment is if a user clicks home button
then i want content layout to be removed and home layout to be visible.
content.fxml
<AnchorPane id="myContent" ... fx:controller="com.ReportController">
rootLayout.fxml
<AnchorPane id="AnchorPane" .. fx:controller="com.ReportController">
<children>
<Button fx:id="home" onAction="#homeBtn" .../>
</children>
</AnchorPane>
In my Controller (In all the fxml file i am pointing to the same controller) class i created
#FXML
private Button home;
#FXML
private AnchorPane myContent;
#FXML
protected void homeBtn(ActionEvent event) throws Exception {
System.out.println("click! homeBtn");
myContent.getChildren().clear();
}
The problem i am facing is i am getting NullPointerException. i.e. myContent.getChildren() is returning null. Could anyone help me in resolving this issue.
You're getting a Null Pointer Exception because Javafx doesn't associate your myContent with the AnchorPane stored in the fxml, and does not attach a reference to that object.
Nodes in fxml files are given their name identifiers by using fx:id. Note, for example, that your #FXML private Button home is marked in the fxml as <Button fx:id="home"...>.
In this case, your #FXML AnchorPane myContent is marked in fxml as <AnchorPane id="myContent"...>, not <AnchorPane fx:id="myContent"...>.
id="" is used only in CSS.
I have this css file which sets the default font size and type in JavaFX application:
.root {
-fx-font: 13px Tahoma;
}
scene.getStylesheets().add(getClass().getResource("/styles/Styles.css").toExternalForm());
I want to update the size and the font type from the Java code dynamically of the root component (all components). How I can do this?
Note:
This code updates the Font type and size of all components into the JavaFX application.
Please consider taking a look at the official JavaFX documentation. There you find the code example which answers your question:
Text t = new Text("That's the text");
t.setFont(Font.font ("Verdana", 20));
UPDATE
In your application controller get an instance of your root pane, e.g. AnchorPane and use the setId("") function to set new style for the whole pane (my actionChange is connected with a button on the pane, which triggers the event/change):
public class AppController implements Initializable {
#FXML
private AnchorPane mainPane;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
#FXML
public void actionChange() {
mainPane.setId("fancytext");
}
}
When pressing the button, the style for the pane is changed. I just used the font-size as an example. Before, you need to specify the new style in your CSS file:
.root {
-fx-font: 12px Tahoma;
}
#fancytext {
-fx-font: 20px Tahoma;
}
That's before:
That's after the button was pressed:
I am creating a simple Weather Application
Here goes the details of my question :-
I have a main Controller (GeoWeatherMain.java). When Appl is run, this class(GeoWeatherMain.class) gets loaded which loads an fxml file.
Below is code for it :-
Parent root = FXMLLoader.load(getClass().getResource("GeoWeatherMainUI.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
Now, GeoWeatherMainUI.fxml has BorderPane object implementation. It consists of a button(on the left pane) which onclick loads another fxml file inside center pane. The skeleton of GeoWeatherMainUI.fxml looks like below:-
<BorderPane fx:id="MainBody" prefHeight="736.0" prefWidth="1140.0" xmlns:fx="http://javafx.com/fxml" fx:controller="geoweather.GeoWeatherUIActionHandlers">
.
.
<Button layoutX="91.0" layoutY="67.0" mnemonicParsing="false" onAction="#getCurrAndForecastWeatherCond" text="Get Weather Details" />
.
.
<BorderPane>
Now GeoWeatherUIActionHandlers.java is another controller which takes care of different button action events.Below is its complete code
public class GeoWeatherUIActionHandlers implements Initializable{
#FXML
BorderPane MainBody;
#FXML
Label LocName;/*LocName is fx id for a label*/
#FXML
private void getCurrAndForecastWeatherCond(ActionEvent event){
try{
Pane centerPane = FXMLLoader.load(getClass().getResource("WeatherDetails.fxml"));
MainBody.setCenter(centerPane);
/*LocName.setText("xyz");*/
}catch (IOException ex){
TextArea excep = new TextArea(ex.toString());
MainBody.setCenter(excep);
}catch(Exception e){
TextArea excep = new TextArea("Inside Exception : \n" + e.toString());
MainBody.setCenter(excep);
}
}
#Override
public void initialize(URL url, ResourceBundle rb){}
}
Now, if I want to update the loaded WeatherDetails.fxml file with new values, how to do that? I tried as in the above commented code.(LocName.setText("xyz")). But, it didn't work (giving NullPointerException).
I went through complete documentation of javafx # docs.oracle.com. No luck. Here also I didn't get the answer. Please guide.
If the LocName is located inside WeatherDetails.fxml then it is excepted behavior that the LocName will be null. Because #FXML Label LocName; is defined in GeoWeatherUIActionHandlers.java which is a controller of GeoWeatherMainUI.fxml. Move LocName from WeatherDetails to GeoWeatherMainUI FXML file and see where you are still getting the error or not.
If your aim is to set the text of the label that is inside WeatherDetails.fxml, then do this work
in the controller of WeatherDetails similar to current GeoWeatherUIActionHandlers, or
in GeoWeatherUIActionHandlers, after loading the WeatherDetails.fxml
get the label by id (not fx:id) from centerPane with ((Label)centerPane.lookup("#myLabel")).setText("xyz"), or
get the controller of WeatherDetails and call getLocName().setText("xyz"). Assuming getter method exists in a controller class.
In JavaFX 1.x, where I've used the FX-Script to setup the Scene, I had the bind keyword:
Dynamic/instant resize in JavaFX
How can I have the same behavior in 2.0?
If you want automatic resize, you should do something like this
private BorderPane root;
#Override
public void start(Stage stage) throws Exception
{
root = new BorderPane();
//ROOT SHOULD BE ONE OF THE LAYOUTS : BorderPane, HBox, VBox, StackPane,
//GridPane, FlowPane
scene = new Scene(root, 500, 500);
stage.setScene(scene);
stage.show();
root.setCenter(new Label("sample label"));
}
I have tried only with BorderPane and it works. Also if you want to create custom
component, your class should extend one of layouts. Automatic resize won't work if your component extends Pane or Group
I think this will help to you.
Best regards
Sandro
I've just found the answer on another plattform:
It is as easy as
FlowPane layout=new FlowPane();
layout.prefWidthProperty().bind(stage.widthProperty());
layout.prefHeightProperty().bind(stage.heightProperty());
If your flow pane has margins, you need perhaps something like this:
innerHorizontalFlowPane.prefWidthProperty().bind(
Bindings.add(-50, stage.widthProperty()))
i have created a linearlayout having 2 table layouts.in the 1st table i have button .now i want to change the 2dn table layout background when i click on the button.not the whole layout ,only the 2nd tablelayout background will be changed.
please help me with some sample code.
In your onCreate() method you need to add a listener to the button and in that listener you can retrieve the view (table layout) and modify its properties. To find the button and the view you're changing you'll need to specify IDs for them in the XML (assuming you're inflating it from XML). Try something like this (untested) code:
Button button = (Button) findViewById(R.id.mybutton);
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(final View view)
{
TableLayout tableLayout = (TableLayout) findViewById(R.id.mytablelayout);
tableLayout.setBackgroundResource(R.drawable.mybackgroundimage);
}
});