I have a SplitPane with two items: progress bar (top pane) and action buttons (e.g., ok/cancel) as the bottom pane.
When the page is load, both panes are displayed.
During initial load, I want to have the top pane hidden and the bottom pane displayed.
The top pane will be display when an action event occurs via button click.
How should I modify the code to be able to execute the described scenario
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import com.ngc.gs.dialogs.widgets.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane fx:id="progressMainAnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="390.0002999999924" prefWidth="398.9998779296875" xmlns:fx="http://javafx.com/fxml" fx:controller="com.ngc.gs.dialogs.widgetexample.MyCheckBoxSelController">
<TreeView fx:id="localTreeView" prefHeight="181.0" prefWidth="363.0" AnchorPane.leftAnchor="15.0" AnchorPane.rightAnchor="21.0" AnchorPane.topAnchor="14.0" />
<SplitPane fx:id="progressSplitPane" focusTraversable="true" maxWidth="1.7976931348623157E308" orientation="VERTICAL" prefHeight="181.0" prefWidth="362.999755859375" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="15.0" AnchorPane.rightAnchor="21.0" AnchorPane.topAnchor="195.0">
<items>
<ProgressBarMessageConsoleWidget id="pBarConsoleWidget" fx:id="pBarConsoleWidget" minHeight="150.0" minWidth="0.0" prefHeight="150.0" prefWidth="361.0" />
<OkCancelButtonsWidget id="actionButtonsWidget" fx:id="actionButtonsWidget" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" />
</items>
</SplitPane>
<stylesheets>
<URL value="#../styles/dialogs.css" />
</stylesheets>
</AnchorPane>
Controller class snippet that sets the splitPane divider:
....
progressSplitPane.setDividerPosition(0, 0.0);
progressSplitPane.setResizableWithParent(progressMainAnchorPane, true);
actionButtonsWidget.getOkBtn().setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent evnt) {
// Show progress bar and message console
progressSplitPane.setDividerPosition(0, 0.75);
pBarConsoleWidget.showProgressConsole();
processCheckBoxSelections();
}
});
...
I resolved this by implementing a GridPane instead and adding listener to the property as described here...
JavaFX HBox hide item
Related
I have a TabPane declared like this :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TabPane?>
<TabPane fx:id="rootNode" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="#dark_theme.css" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.AppController" />
And I want to add tabs from my controller. So I do :
jsonConfig.getAvailableChannelIds().forEach( chId -> {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("tab_item.fxml"));
Tab item = fxmlLoader.load();
item.setText(String.format("%d", chId));
rootNode.getTabs().add(item);
}catch (Exception e) {
e.printStackTrace();
}
});
"tab_item.fxml" looks as follows :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.layout.VBox?>
<Tab xmlns:fx="http://www.w3.org/1999/XSL/Transform">
<VBox>
<fx:include source="test.fxml"/>
</VBox>
</Tab>
And finally "test.fxml" :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: red;" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" />
And here is what I have :
What am I missing to fill the Tab content with the red square ?
Most layout panes, such as VBox, will by default try to size their content to the preferred size, and will make every attempt to keep the sizes within the constraints specified as the minimum and maximum.
I recommend reading the old Oracle layout tutorial. It was written a long time ago (before Java 8), so the code style is a bit out of date, but the layout concepts are all still relevant. Also read the Javadocs for the layout package, and presumably you already read the Javadocs for any layout component you are using (if not, you should always read the docs for the classes you use).
You have
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0"
style="-fx-background-color: red;"
xmlns="http://javafx.com/javafx/19"
xmlns:fx="http://javafx.com/fxml/1" />
which explicitly sets the preferred size to 600x400 pixels, and additionally sets the minimum and maximum sizes to -Infinity, which is the sentinel value Region.USE_PREF_SIZE. Therefore, the VBox will always size the content to 600x400 pixels (as long as there is enough space in the VBoxto do so).
Remove all those settings (I corrected the namespace too, though you don't really need it here):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane style="-fx-background-color: red;"
xmlns:fx="http://javafx.com/fxml" />
Now the VBox will still attempt to set the content to its preferred size, which by default is computed from its own content. Since the anchor pane is empty, that preferred size will be computed as 0x0. However, since the max size is now unconstrained, you can tell the VBox to let it grow:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.layout.VBox?>
<Tab xmlns:fx="http://javafx.com/fxml/">
<VBox fillWidth="true">
<fx:include source="test.fxml" VBox.vgrow="ALWAYS" />
</VBox>
</Tab>
Now the content defined in test.fxml will fill the VBox. The behavior of a Tab is to let its content fill the entire region of the tab, so the VBox will fill the tab.
Of course, it's not really clear why you are wrapping test.fxml in a VBox in the first place. Since the tab will be filled by its content by default, why not just simplify to
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<Tab xmlns:fx="http://javafx.com/fxml/">
<fx:include source="test.fxml" />
</Tab>
Here is a complete example, with all the unnecessary hard-coded sizes and redundant layout panes removed:
HelloApplication.java:
package org.jamesd.examples.tab;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
hello-view.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TabPane?>
<TabPane fx:id="rootNode"
tabClosingPolicy="UNAVAILABLE"
xmlns:fx="http://javafx.com/fxml/"
fx:controller="org.jamesd.examples.tab.AppController" />
AppController.java:
package org.jamesd.examples.tab;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
public class AppController {
#FXML
private TabPane rootNode ;
public void initialize() {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("tab_item.fxml"));
Tab item = fxmlLoader.load();
item.setText(String.format("%d", 42));
rootNode.getTabs().add(item);
}catch (Exception e) {
e.printStackTrace();
}
}
}
tab-item.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<Tab xmlns:fx="http://javafx.com/fxml/">
<fx:include source="test.fxml" />
</Tab>
and test.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane style="-fx-background-color: red;"/>
Ok, so I found at least a workaround here -> just wrap fx:include with AnchorsPane and it works :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.layout.AnchorPane?>
<Tab xmlns:fx="http://www.w3.org/1999/XSL/Transform">
<content>
<AnchorPane>
<fx:include source="test.fxml" AnchorPane.topAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.bottomAnchor="0"/>
</AnchorPane>
</content>
</Tab>
I made an anchorpane with an fxml and a controller. I also made a borderpane with a view, fxml and another controller. How can I add the anchorpane inside the borderpane? The reason I want them in separate fxml and controller is that the borderpane is a lot of code and this would make everything look cleaner.
I thought it would work like this but it doesn't.
Borderfxml:
?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.textfield.*?>
<BorderPane fx:controller="Bordercontroller" xmlns:fx="http://javafx.com/fxml"
prefHeight="200" prefWidth="320">
<top>
</top>
<left>
</left>
<center>
</center>
<right>
<Anchorpane fx:id="Same id as my anchorpane"/>
</right>
<bottom>
</bottom>
</BorderPane>
I am trying to make a login page which is full screen,I followed another question in stackoverflow and made my login window it looks perfect with all controls, buttons etc aligned to center ,But as soon as I change the screen resolution every thing becomes unaligned . how can I solve this?.I am using scene builder
fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1360.0" spacing="20.0" styleClass="background" stylesheets="#../UICoreComponents/JMetroDarkTheme.css" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.MyCompany.attendanceMaster.LoginController">
<children>
<Pane prefHeight="200.0" prefWidth="278.0">
<children>
<TextField fx:id="userNameTF" layoutX="6.0" layoutY="55.0" prefHeight="25.0" prefWidth="248.0" promptText="Username" />
<Button layoutX="14.0" layoutY="141.0" mnemonicParsing="false" onAction="#loginBtnClicked" prefHeight="25.0" prefWidth="101.0" text="Login" />
<Button layoutX="145.0" layoutY="141.0" mnemonicParsing="false" onAction="#clearBtnClicked" prefHeight="25.0" prefWidth="101.0" text="Clear" />
<Label layoutX="99.0" layoutY="14.0" prefHeight="17.0" prefWidth="62.0" text="Login" textFill="WHITE">
<font>
<Font size="22.0" />
</font></Label>
<PasswordField fx:id="passwordTF" layoutX="6.0" layoutY="100.0" prefHeight="25.0" prefWidth="248.0" promptText="Password" />
</children>
</Pane>
</children>
<padding>
<Insets left="550.0" right="550.0" />
</padding>
</VBox>
Main.java
import com.MyCompany.Network.ClientMaster;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Screen;
import javafx.stage.Stage;
/**
*
* #author shersha
*/
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception {
new StaticController();
new ClientMaster();
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.setFullScreen(true);
stage.setResizable(false);
Parent root = StaticController.LOGIN_LOADER.getRoot();
Scene scene = new Scene(root);
scene.getStylesheets().add("com/MyCompany/UICoreComponents/JMetroDarkTheme.css");
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
My screen resolution is 1360X768 perfectly alligned
**Screen resolution at 1024X768 **
My final question is how can I make a javafx application that will run screen resolution Independent?(My window size is maximized and not resizable)
Thank you.
Your layout is based on a VBox and then you are using padding to align it. As these values will be the same for all window sizes, it will only work in one case.
Instead you should use a StackPane or which centers the content. Into that StackPane you add your Pane, without any padding. Eventually you need to bind the scene width and heigh to the values of the StackPane.
I have got an FXML file in which there is a custom component declared. This component has some logic that requires a reference to another component declared in the same fxml file. The FXML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.layout.AnchorPane?>
<BorderPane xmlns:fx="http://javafx.com/fxml" prefWidth="800" prefHeight="400" fx:controller="test.MyController">
<top>
<HBox spacing="10">
<Label text="Test"/>
<TextField fx:id="testField"/>
</HBox>
</top>
<center>
<AnchorPane>
<children>
<VBox fx:id="customBox" visible="false" prefHeight="400" prefWidth="400"
VBox.vgrow="ALWAYS"
initiator="#testField"/>
</children>
</AnchorPane>
</center>
</BorderPane>
So, I need to set the initiator property of customBox. With this, I am getting Caused by: java.lang.IllegalArgumentException: Unable to coerce #testField to class javafx.scene.control.TextField. Any suggestions?
I don't have time to test this, but I think
<KontrollkoderVBox fx:id="customBox" visible="false" prefHeight="400" prefWidth="400"
VBox.vgrow="ALWAYS"
initiator="$testField"/>
will work. See "variable resolution" in the FXML documentation.
You can even do things like binding a StringProperty in KontrolkoderVBox to the TextField's textProperty() by referencing ${testField.text}.
You may set the id of textField (say id="testFieldId" which is different from fx:id) into initiator and do lookup:
// in VBox #customBox
TextField tf = (TextField) getScene().lookup(getInitiator());
where getInitiator() returns String = "#testFieldId".
It's working fine while I am running the application directly from eclipse. but after building the application using ant, generated jar file it's not working.
However if I removed Styleclass="theme" from fxml it's working fine using jar file as well
Java File
public class MainClass extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().
getResource("/resources/fxmlDocument/Sample.fxml"));
stage.setTitle("SAMPLE");
Scene scene= new Scene(root);
scene.getStylesheets().add(getClass().getClassLoader().
getResource("resources/css/sample.css").toExternalForm());
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
}
Fxml File:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" styleClass="theme" xmlns:fx="http://javafx.com/fxml" fx:controller="com.integra.test.MainClassController">
<children>
<Label layoutX="300.0" layoutY="184.0" text="Great..!" />
<Button fx:id="clickbutton" layoutX="207.0" layoutY="184.0" mnemonicParsing="false" text="clickme" />
<TextField fx:id="text1" layoutX="207.0" layoutY="220.0" prefWidth="200.0" />
<Button fx:id="closebutton" layoutX="459.0" layoutY="318.0" mnemonicParsing="false" onAction="#closeButtonAction" prefHeight="37.0" prefWidth="75.0" text="Close" />
</children>
</AnchorPane>
You also use this for adding Style sheets to the controls.
control.getStylesheets().add
(MainClass.class.getResource("Sample.css").toExternalForm());
make sure css file in the same package or specify source path.
Second way is to use scene builder and add css using scene builder. You will get tutorial for this.