I have a question.. well, I use this code to get my node's coordinates
Bounds localToScreen = myNode.localToScene(myNode.getBoundsInLocal());
localToScreen.getMinX();
localToScreen.getMinY();
localToScreen.getWidth();
localToScreen.getHeight();
but this code just sometimes works and In the other times it shows wrong results.. so is there any thing special about using this code? why doesn't it work any times? In scenebuilder all the node's coordinates are right.
this is an example
my fxml file is
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="anchor" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.FXMLDocumentController">
<children>
<HBox fx:id="hbox" layoutX="147.0" layoutY="67.0" prefHeight="34.0" prefWidth="200.0">
<children>
<TextField />
<Button mnemonicParsing="false" text="Button" />
</children>
</HBox>
</children>
</AnchorPane>
and my controller is
public class FXMLDocumentController implements Initializable {
#FXML
private AnchorPane anchor;
#FXML
private HBox hbox;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
Bounds localToScreen = hbox.localToScene(hbox.getBoundsInLocal());
System.out.print(""+
localToScreen.getMinX() +" "+
localToScreen.getMinY() +" "+
localToScreen.getWidth()+" "+
localToScreen.getHeight()
);
// TODO
}
the result is
147.0 67.0 0.0 0.0
width and height should not be 0!
please help.. thanks
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>
To summarize, I have various FXML files and various corresponding controllers, and to switch between them I am using the following code:
#FXML
public void openInputPane() throws IOException {
BorderPane inputMenu = FXMLLoader.load(getClass().getResource("inputSection/firstPage/inputEquationMenu.fxml"));
mainBorderPane.getChildren().setAll(inputMenu);
}
My main fxml file is a GridPane and the rest are BorderPanes, and this method of using .getChildren().setAll(anotherPane) works perfectly until I try to return to the main GridPane:
public void goToMainMenu() throws IOException {
URL url = new File("C:\\Users\\Luisa" +
"\\IdeaProjects\\IA\\src\\sample\\mainmenu.fxml").toURI().toURL();
GridPane mainMenu = FXMLLoader.load(url);
successMessageBorderPane.getChildren().setAll(mainMenu);
}
The above code does display the original main menu, but messes up the formatting, attached are pictures of the main menu when I first open the programme and the main menu after returning to it.
after returning to main
main at the start of the programme
My question is, what is messing up the formatting when I go back to the main page, and what do I have to do to fix it?
For more details I'm attaching the fxml file for the main GridPane and the last BorderPane (the one where a button is clicked to return to the main GridPane) and their respective controllers.
mainmenu.fxml
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.text.Font?> <?import javafx.scene.layout.HBox?>
<GridPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml"
stylesheets="#resources/styles.css" fx:id="mainBorderPane" prefHeight="400" prefWidth="500" vgap="20"
hgap="20" alignment="CENTER">
<HBox GridPane.columnIndex="0" GridPane.rowIndex="0">
<Label text="Physics Formula Storage">
<font>
<Font size="40"/>
</font>
</Label>
</HBox>
<HBox GridPane.rowIndex="1" spacing="35">
<Button text="Insert Equations" onAction="#openInputPane"/>
<Button text="Use Equations"/>
</HBox>
<HBox GridPane.rowIndex="2" spacing="20"
prefWidth="340">
<Label text="Input new equations along with their properties into the storage system" prefWidth="150"
style= "-fx-font-size: 14"/>
<Label text="Find and use equations already in the storage system" prefWidth="150" style= "-fx-font-size: 14"/>
</HBox>
</GridPane>
Controller
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import java.io.IOException;
public class Controller {
#FXML
GridPane mainBorderPane;
// switching to the input pane if the button is clicked
#FXML
public void openInputPane() throws IOException {
BorderPane inputMenu = FXMLLoader.load(getClass().getResource("inputSection/firstPage/inputEquationMenu.fxml"));
mainBorderPane.getChildren().setAll(inputMenu);
}
}
successMessageMenu.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Line?>
<?import javafx.scene.text.Font?>
<BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.inputSection.thirdPage.SuccessMessageController"
prefHeight="400.0" prefWidth="600.0" stylesheets="#../../resources/styles.css"
fx:id="successMessageBorderPane">
<padding>
<Insets top="30" right="50" bottom="30" left="50"/>
</padding>
<top>
<VBox prefHeight="50">
<Label alignment="BOTTOM_LEFT" text="Equation added successfully">
<font>
<Font size="17"/>
</font>
</Label>
<Line startX="50" startY="50" endX="550" endY="50"/>
</VBox>
</top>
<center>
<VBox prefHeight="300" alignment="CENTER">
<Label text="Equation has been added successfully" style="-fx-font-style: italic">
<font>
<Font size="40"/>
</font>
</Label>
</VBox>
</center>
<bottom>
<VBox alignment="BOTTOM_CENTER" prefHeight="50">
<Button text="Return to main menu" fx:id="mainMenuButton"
onAction="#goToMainMenu"/>
</VBox>
</bottom>
</BorderPane>
successMenuController
public class SuccessMessageController {
#FXML
Button mainMenuButton;
#FXML
BorderPane successMessageBorderPane;
public void goToMainMenu() throws IOException {
URL url = new File("C:\\Users\\Luisa" +
"\\IdeaProjects\\IA\\src\\sample\\mainmenu.fxml").toURI().toURL();
GridPane mainMenu = FXMLLoader.load(url);
successMessageBorderPane.getChildren().setAll(mainMenu);
}
}
(it is my first time asking a question, do tell me if I need to add anymore code, thank you!)
so i'm creating this application using javafx which has one login screen, but I've had no sucess at all in this, I have been working on this little part of the project for some days and it simply didn't work in any way I try to do it, I watched some tutorials and most of them were making like the codes below, yet it didn't work for me, if anyone can help me with that explaining why my label text doesn't change(that's how I'm testing if the login was sucessful) it would be nice, here are the codes:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/view/telaLogin.fxml"));
stage.setTitle("morrer");
stage.setScene(new Scene(root, 380, 450));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller:
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.event.ActionEvent;
public class LoginController {
#FXML
private TextField username;
#FXML
private PasswordField pfSenha;
#FXML
private Label labelTeste;
public void login(ActionEvent event) throws Exception {
if(username.getText().equals("admin") && pfSenha.getText().equals("admin")) {
labelTeste.setText("sucess");
} else {
labelTeste.setText("fail");
}
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<BorderPane fx:id="telaLogin" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="333.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.LoginController">
<center>
<VBox alignment="CENTER" prefHeight="408.0" prefWidth="333.0" BorderPane.alignment="TOP_CENTER">
<children>
<TextField fx:id="username" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="25.0" prefWidth="184.0" promptText="Usuáro">
<VBox.margin>
<Insets />
</VBox.margin>
</TextField>
<PasswordField fx:id="pfSenha" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="25.0" prefWidth="184.0" promptText=" Senha">
<VBox.margin>
<Insets top="50.0" />
</VBox.margin>
</PasswordField>
<Button fx:id="btnEntrar" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" text="Button">
<VBox.margin>
<Insets right="25.0" top="50.0" />
</VBox.margin>
</Button>
</children>
</VBox>
</center>
<bottom>
<Label fx:id="labelTeste" prefHeight="23.0" prefWidth="289.0" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
Button does nothing because FX does not know it should call login method in your LoginController.
Following this FX GUI tutorial you have to specify called method in onAction attribute. So your button should be defined:
<Button onAction="#login" fx:id="btnEntrar" maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" text="Button">
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
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.