Can I change the alignment of one element in a VBox? - javafx

If I put controls (or layouts with controls) in a VBox all elements get aligned the same way. I want to change the alignment of one of those elements like this
I tried to change the alignment of Button 2by calling setAlignment() on it, but calling setAlignment() on an individual element doesn't change the alignment within the VBox. (The JavaDoc's explanation of Button.setAlignment() is useless.)
I was able to change the alignment of Button 4 by using an HBox and setting its alignment. I'd rather not introduce extra Nodes if I don't have to. Is there a way to change the alignment of one Node in a layout container without having to use another layout?
Here's the code:
public class VBoxAlignmentDemoApplication extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/VBoxAlignmentDemo.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("VBoxAlignmentDemo");
primaryStage.show();
}
}
public class VBoxAlignmentDemoController implements Initializable {
#FXML
VBox vbox;
#FXML
Button button2;
public void initialize(URL arg0, ResourceBundle arg1) {
button2.setAlignment(Pos.CENTER_RIGHT);
}
}
<VBox fx:id="vbox" alignment="CENTER_LEFT" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="vbox.alignment.demo.VBoxAlignmentDemoController">
<children>
<Button mnemonicParsing="false" text="Button 1" />
<Button fx:id="button2" mnemonicParsing="false" text="Button 2" />
<Button mnemonicParsing="false" text="Button 3" />
<HBox alignment="CENTER">
<children>
<Button mnemonicParsing="false" text="Button 4" />
</children>
</HBox>
</children>
</VBox>

Related

Can not create clearable textField using ControlsFX

I have created TextField using Scene Builder but when I tried it with KeyEvent but it doesn't work.
public class FXMLDocumentController implements Initializable {
#FXML
private TextField searchPatient;
#FXML
void keyTyped(KeyEvent event) {
this.searchPatient = TextFields.createClearableTextField();
}
}
Here is main class:
public class MyFX 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);
}
}
Here is FXMLDocument.fxml:
<AnchorPane id="AnchorPane" prefHeight="597.0" prefWidth="726.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.homeo.home.FXMLDocumentController">
<children>
<TextField fx:id="searchPatient" layoutX="14.0" layoutY="109.0" onKeyTyped="#keyTyped" prefHeight="26.0" prefWidth="372.0" promptText="Search" />
</children>
</AnchorPane>
I don't want to relay on code for designing that's why I want to use ControlsFX with IDE generated code.
I'm expecting textfield must show clear icon as I enter few text in a textfield that's called clearableTextFieldf.
But with the all code above doesn't work as I expected.
It does not create ClearableTextField
You're creating the TextField in the KEY_TYPED event handler of a conventional TextField placed in your scene. The newly created TextField is never added to any scene though.
You could use the fx:factory attribute to use the static method for creating the TextField that FXMLLoader adds to the scene:
...
<?import org.controlsfx.control.textfield.TextFields?>
<AnchorPane id="AnchorPane" prefHeight="597.0" prefWidth="726.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.homeo.home.FXMLDocumentController">
<children>
<TextFields fx:factory="createClearableTextField" fx:id="searchPatient" layoutX="14.0" layoutY="109.0" prefHeight="26.0" prefWidth="372.0" promptText="Search" />
</children>
</AnchorPane>
You could alternatively use the initialize method to create&add your TextField instead:
public class FXMLDocumentController implements Initializable {
...
#FXML
private AnchorPane anchorPane;
#Override
public void initialize(URL location, Resources resources)
searchPatient = TextFields.createClearableTextField();
searchPatient.setLayoutX(14.0);
searchPatient.setLayoutY(109.0);
searchPatient.setPrefSize(372.0, 26.0);
searchPatient.setPromptText("Search");
anchorPane.getChildren().add(searchPatient);
...
}
}
<AnchorPane fx:id="anchorPane" id="AnchorPane" prefHeight="597.0" prefWidth="726.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.homeo.home.FXMLDocumentController" />

How to resize child AnchorPanes within a VBox JavaFX

This is my main UI Main UI
I have a VBox (Fxid:datePane) within a AnchorPane. The Vbox is blue in color.
When the button with the label "Add" is clicked, a "second.fxml" file is loaded into the VBox (Fxid:datePane).
The fxml file loaded takes the height and width of the Vbox.
The second.fxml has a VBox which is red in color.
However if i resize the screen, the loaded file doesn't change its height and width accordingly.
After resizing the screen
How do i make sure the loaded fxml file takes the width and height of its parent VBox (Fxid:datePane) ???
This is my FxmlController.java file
#FXML
private Button btnAdd;
#FXML
private VBox datePane;
#FXML
private VBox vbxsecond;
#FXML
private VBox vbxThird;
#FXML
private AnchorPane apLoader;
VBox v;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
double w = apLoader.getWidth();
double h = apLoader.getHeight();
System.out.println(h);
}
public void setDataPane(Node node) {
// update VBox with new form(FXML) depends on which button is clicked
datePane.getChildren().setAll(node);
}
public VBox fadeAnimate(String url) throws IOException {
v = (VBox) FXMLLoader.load(getClass().getResource(url));
FadeTransition ft = new FadeTransition(Duration.millis(1500));
ft.setNode(v);
ft.setFromValue(0.1);
ft.setToValue(1);
ft.setCycleCount(1);
ft.setAutoReverse(false);
double w = datePane.getWidth();
double h = datePane.getHeight();
v.setPrefHeight(h);
v.setPrefWidth(w);
ft.play();
return v;
}
public void loadPane() throws IOException {
try{
setDataPane(fadeAnimate("/resources/second.fxml"));
}catch(IOException e)
{
e.printStackTrace();
}
}
public void loadPane2 () throws IOException {
try{
setDataPane(fadeAnimate("/resources/third.fxml"));
}catch(IOException e)
{
e.printStackTrace();
}
}
This is my Main.java file
#FXML
private VBox vbxsecond;
#FXML
private VBox datePane;
#Override
public void start(Stage primaryStage) {
try {
//BorderPane root = new BorderPane();
Parent root = FXMLLoader.load(getClass().getResource("/resources/dashboard.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
//primaryStage.setMaximized(true);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
This is my dashboard.fxml file
AnchorPane minHeight="800.0" prefHeight="800.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.FxmlController">
<children>
<SplitPane dividerPositions="0.29797979797979796" layoutX="14.0" layoutY="14.0" prefHeight="800.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="798.0" prefWidth="192.0">
<children>
<Button fx:id="btnAdd" layoutX="22.0" layoutY="122.0" mnemonicParsing="false" onAction="#loadPane" prefHeight="25.0" prefWidth="51.0" text="Add" AnchorPane.leftAnchor="22.0" AnchorPane.topAnchor="122.0" />
<Button fx:id="btnadd2" layoutX="57.0" layoutY="281.0" mnemonicParsing="false" onAction="#loadPane2" text="ADD second" />
</children>
</AnchorPane>
<AnchorPane fx:id="apLoader" minHeight="0.0" minWidth="0.0" prefHeight="158.0" prefWidth="814.0">
<children>
<VBox fx:id="datePane" layoutX="10.0" layoutY="23.0" prefHeight="798.0" prefWidth="628.0" style="-fx-background-color: Blue;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
This is my second.fxml file
<VBox fx:id="vbxsecond" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="814.0" style="-fx-background-color: Red;" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label fx:id="vbxSecond" text="HELLOOO" VBox.vgrow="ALWAYS">
<font>
<Font size="96.0" />
</font>
</Label>
</children>
</VBox>
This is my third.fxml file
<VBox fx:id="vbxThird" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="814.0" style="-fx-background-color: Pink;" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label text="Third HELOO" VBox.vgrow="ALWAYS">
<font>
<Font size="85.0" />
</font>
</Label>
</children>
</VBox>
I solved the problem. I just had to set the values of the VBox in the second.fxml and VBox (Fxid:datePane) in the main.fxml to
AnchorPane.topAnchor="0.0"
AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0"
and it worked.

JavaFX #FXML binding from within Java code

I have a custom JavaFX component extending the Tab class:
public class MyTab extends Tab implements Initializable {
#FXML private TextField myInput;
private final MyDTO dto;
public MyTab(MyDTO dto) {
super();
this.dto = dto;
final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/my-tab.xml"));
fxmlLoader.setResources(MSG.getResourceBundle());
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
}
catch (IOException exception) {
throw new RuntimeException(exception);
}
}
#Override
public void initialize(URL url, ResourceBundle res) {
setText("My Tab");
myInput.setText(dto.getValue()); // !!!
}
}
With the FXML:
<fx:root type="javafx.scene.control.Tab" xmlns:fx="http://javafx.com/fxml">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Label id="myLabel" layoutX="14.0" layoutY="14.0" text="Text:" />
<TextField id="myInput" layoutX="162.0" layoutY="10.0" prefHeight="25.0" prefWidth="300.0" />
</children>
</AnchorPane>
</content>
</fx:root>
I need to create this objects (custom tabs) dynamically from the java code:
final MyTab myTab = new MyTab(new MyDTO(...));
tabPane.getTabs().add(myTab);
When I use it like this, the #FXML binding doesn't work and the line
myInput.setText(dto.getValue());
throws NullPointerException. When the line with the setting of the text from the code is commented, the input is showned, so the problem is only in the binding.
I am using JavaFX 2 for Java 1.7
Thank you for any idea!
Solution is very easy, I just overlooked the mistake in the FXML code:
Should be
<TextField fx:id="myInput" ...
instead of
<TextField id="myInput" ...

how to change parent fxml content from action perform on child fxml component?

I created JavaFX application and want to distribute complete functionality among different FXML with hierarchy and MVC structure.
At the start time RoolLayout.fxml is load which is parent FXML
RootLayout.fxml
<BorderPane prefHeight="400.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nikunj.drclinic.controller.RootLayoutController">
<center>
<AnchorPane fx:id="dashboard" BorderPane.alignment="CENTER" />
</center>
<top>
<HBox BorderPane.alignment="CENTER">
<children>
<fx:include fx:id="mainMenu" source="MainMenuBar.fxml" />
</children>
</HBox>
</top>
</BorderPane>
For this used controller is RootLayoutController.java
public class RootLayoutController {
#FXML
private MainMenuBarController mainMenuBarController;
#FXML
private AnchorPane dashboard;
#FXML
private void initialize() {
// Initialize the person table with the two columns.
}
}
From inside this MainMenuBar.fxml file is also loaded which is child fxml file
MainMenuBar.fxml
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nikunj.drclinic.controller.MainMenuBarController">
<children>
<MenuBar layoutY="2.0" prefWidth="1000.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#closeApplication" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Patient Detail">
<items>
<MenuItem fx:id="addPatiendMenuItem" mnemonicParsing="false" onAction="#addPatient" text="Add Patient" />
<MenuItem mnemonicParsing="false" text="Find Patient" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>
controller file for this MainMenuBar.fxml is MainMenuBarController.java
public class MainMenuBarController {
#FXML
private MenuItem addPatiendMenuItem;
#FXML
private MenuItem findPatientMenuItem;
#FXML
public void closeApplication(){
System.exit(0);
}
#FXML
public void addPatient(ActionEvent event){
}
}
Now on selection of menu item addPatiendMenuItem from controller addPatient(ActionEvent event) method is called.
From this method how can i change the AnchorPane fx:id = "dashboard" which is component of the parent fxml (RootLayout.fxml) file.
Suppose i want to load content of third fxml (i.e. Dashboard.fxml) in this AnchorPane, how can i do that?
I spend lots of hours to find, how to change parent controller component from the action performed on child controller component?
Create a property in the MainMenuBarController that represents the state you are changing ("view state"). Making this make sense depends on knowing a bit more about your application, but you might do something like
public class MainMenuBarController {
private final BooleanProperty addPatientRequested = new SimpleBooleanProperty();
public BooleanProperty addPatientRequestedProperty() {
return addPatientRequested ;
}
public final boolean isAddPatientRequested() {
return addPatientRequestedProperty().get();
}
public final boolean setAddPatientReqested(boolean requested) {
addPatientReqestedProperty().set(requested);
}
#FMXL
private void addPatient(ActionEvent event) {
setAddPatientRequested(true);
}
}
Then in the "parent" controller do
public class RootLayoutController {
#FXML
private MainMenuBarController mainMenuBarController;
#FXML
private AnchorPane dashboard;
#FXML
private void initialize() {
// Initialize the person table with the two columns.
mainMenuBarController.addPatientRequestedProperty().addListener((obs, wasRequested, isNowRequested) -> {
if (isNowRequested) {
// code to execute...
}
});
}
}
Depending on your application logic, you might want a different property, e.g. in the MainMenuBarController define
ObjectProperty<Node> display = new SimpleObjectProperty<>();
which would store the node the RootLayoutController is supposed to display. The structure would be similar, set that property in the addPatient handler method and listen to it in the RootLayoutController

javafx invoking button to draw rectangle on scene

I am creating a simple application in javafx. The main screen has two tabs and each tab has a button. When (button)btn2 in tab2 is clicked, a rectangle should be displayed on the scene.
Here is my code.
Main class:
public class check extends Application
{
public Stage primaryStage;
private BorderPane rootLayout;
#Override
public void start(Stage primaryStage)
{
this.primaryStage = primaryStage;
this.primaryStage.setTitle("TabsExample");
RootLayout();
}
public void RootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(check.class.getResource("/view/tabs.fxml"));
rootLayout = (BorderPane) loader.load();
primaryStage.setScene(new Scene(rootLayout, 500, 500));
primaryStage.show();
control controller = loader.getController();
} catch (IOException e) {
e.printStackTrace();
}
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
Control.java
public class control {
#FXML
private Tab tab1;
#FXML
private Tab tab2;
#FXML
private Button btn1;
#FXML
private Button btn2;
#FXML
private AnchorPane A2;
#FXML
private AnchorPane A1;
public control(){}
private check mainclass;
#FXML public void handleSubmitButtonAction(ActionEvent event)
{
System.out.println("button clicked");
Rectangle r = new Rectangle();
r.setX(50);
r.setY(50);
r.setWidth(200);
r.setHeight(100);
r.setArcWidth(20);
r.setArcHeight(20);
A2.getChildren().add(r);
}
public void setcheck(check ch) {
this.mainclass = ch;
}
}
****FXML:****
<BorderPane maxHeight="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.control">
<top>
<TabPane prefHeight="1754.0" prefWidth="1374.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
<tabs>
<Tab id="tab1" text="Draw Circle">
<content>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button id="btn1" layoutX="23.0" layoutY="44.0" mnemonicParsing="false" text="rectangle" />
</children>
</AnchorPane>
</content></Tab>
<Tab id="tab2" text="Draw Rectangle">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button id="btn2" layoutX="20.0" layoutY="58.0" mnemonicParsing="false" onAction="#handleSubmitButtonAction" prefHeight="15.0" prefWidth="77.0" text="circle" />
</children></AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</top>
</BorderPane>
I apologize for a very long question. With this code, the button action listener is invoked and the message "Button clicked" is printed on the console. But, I do not understand why the rectangle is not drawn on the screen.
It looks like you're missing the ID for the AnchorPane in your FXML. Also, the appropriate tag to use here is "fx:id". You can read a bit more about that here: What's the difference between fx:id and id: in JavaFX?
Below is the corrected FXML
<BorderPane maxHeight="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.control">
<top>
<TabPane prefHeight="1754.0" prefWidth="1374.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
<tabs>
<Tab fx:id="tab1" text="Draw Circle">
<content>
<AnchorPane fx:id="A1" prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="btn1" layoutX="23.0" layoutY="44.0" mnemonicParsing="false" text="rectangle" />
</children>
</AnchorPane>
</content></Tab>
<Tab fx:id="tab2" text="Draw Rectangle">
<content>
<AnchorPane fx:id="A2" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button fx:id="btn2" layoutX="20.0" layoutY="58.0" mnemonicParsing="false" onAction="#handleSubmitButtonAction" prefHeight="15.0" prefWidth="77.0" text="circle" />
</children></AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</top>
</BorderPane>

Resources