I have a graph look like this. I want to update view when I change slider. However, all elements will stacked together look like that when I change slider. So what can I do to get a new view.
my app's structrue:
Circle and QuadCurve -> Group -> ScrollPane -> BorderPane -> Scene -> Stage
This app demonstrates what you are trying to achieve. Comments are in the code.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication6 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();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.control.Slider;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable {
#FXML
private Group groupMain;
#FXML
private Circle cirMain, cirCenter, cirRadius1, cirRadius2, cirRadius3;
#FXML
private Slider sliderMain;
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML void handleButton(ActionEvent event)
{
double radius = cirMain.getRadius();//Get transparent mainCircle radius
System.out.println(radius + " : " + cirMain.getLayoutX() + " : " + cirMain.getLayoutY());
cirRadius1.setRadius(20);
cirRadius1.setLayoutX(radius * Math.cos(50) + cirMain.getLayoutX());//set cirRadius1 to x location on circumference of cirMain
cirRadius1.setLayoutY(radius * Math.sin(50) + cirMain.getLayoutY());//set cirRadius1 to y location on circumference of cirMain
cirRadius1.setFill(Color.RED);
cirRadius2.setRadius(10);
cirRadius2.setLayoutX(radius * Math.cos(175) + cirMain.getLayoutX());//set cirRadius2 to x location on circumference of cirMain
cirRadius2.setLayoutY(radius * Math.sin(175) + cirMain.getLayoutY());//set cirRadius2 to y location on circumference of cirMain
cirRadius2.setFill(Color.YELLOW);
cirRadius3.setRadius(15);
cirRadius3.setLayoutX(radius * Math.cos(300) + cirMain.getLayoutX());//set cirRadius3 to x location on circumference of cirMain
cirRadius3.setLayoutY(radius * Math.sin(300) + cirMain.getLayoutY());//set cirRadius3 to y location on circumference of cirMain
cirRadius3.setFill(Color.GREEN);
sliderMain.setValue(radius);//set slider value to current cirMain radius
//This listener moves the circle inward or outward depending on the slider. It also changes the radius of cirMain's radius
sliderMain.valueProperty().addListener((obs, oldVal, newVal)->{
cirMain.setRadius(newVal.doubleValue());
cirRadius1.setLayoutX(newVal.doubleValue() * Math.cos(50) + cirMain.getLayoutX());
cirRadius1.setLayoutY(newVal.doubleValue() * Math.sin(50) + cirMain.getLayoutY());
cirRadius2.setLayoutX(newVal.doubleValue() * Math.cos(175) + cirMain.getLayoutX());
cirRadius2.setLayoutY(newVal.doubleValue() * Math.sin(175) + cirMain.getLayoutY());
cirRadius3.setLayoutX(newVal.doubleValue() * Math.cos(300) + cirMain.getLayoutX());
cirRadius3.setLayoutY(newVal.doubleValue() * Math.sin(300) + cirMain.getLayoutY());
});
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Circle?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="518.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication6.FXMLDocumentController">
<children>
<Circle fx:id="cirMain" fill="#ededed00" layoutX="300.0" layoutY="200.0" radius="175.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fx:id="cirCenter" fill="DODGERBLUE" layoutX="300.0" layoutY="200.0" radius="14.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fx:id="cirRadius1" fill="DODGERBLUE" layoutX="177.0" layoutY="156.0" radius="25.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fx:id="cirRadius2" fill="DODGERBLUE" layoutX="412.0" layoutY="166.0" radius="35.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fx:id="cirRadius3" fill="DODGERBLUE" layoutX="237.0" layoutY="290.0" radius="27.0" stroke="BLACK" strokeType="INSIDE" />
<Button layoutX="288.0" layoutY="479.0" mnemonicParsing="false" onAction="#handleButton" text="Button" />
<Slider fx:id="sliderMain" blockIncrement="1.0" layoutX="34.0" layoutY="418.0" max="200.0" prefHeight="38.0" prefWidth="551.0" showTickLabels="true" showTickMarks="true" />
</children>
</AnchorPane>
Related
I have seen this question on "JavaFX: how to create slide in animation effect for a pane (inside a transparent stage)".
And I don't understand that partial code on the last comment posted by John Astralidis. It seems to solve my problem. I would like to slide a pane with a shadow stage. Now my problem is the slide animation play out of my visual root pane bound, it just play with stage (or actual root pane) bound.
My visual root pane is a child of actual root pane, I set the actual root pane with padding and Corlor.TRANSPARENT to implement my visual root pane shadow effect.
here is the code I had modified from John Astralidis and Felipe Guizar Diaz.
the start code:
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
stage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(root);//
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
the FXMLDocument.fxml:
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="anchorPane" prefWidth="500" prefHeight="500" style="-fx-background-color: transparent;"
fx:controller="leftslidemenusample.FXMLDocumentController">
<children>
<ToolBar AnchorPane.topAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" minHeight="56.0" >
<Button text="menu" fx:id="menu" />
</ToolBar>
<StackPane fx:id="mainContent" style="-fx-background-color:rgba(0,0,0,0.30)" AnchorPane.bottomAnchor="0.0" AnchorPane.topAnchor="56.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" >
<children>
</children>
</StackPane>
<AnchorPane fx:id="navList" style="-fx-background-color:white" AnchorPane.topAnchor="56.0" AnchorPane.bottomAnchor="0.0" prefWidth="180.0" translateX="-180" >
<children>
<Label text="left side menu"/>
</children>
</AnchorPane>
</children>
and the controller FXMLDocumentController.java
public class FXMLDocumentController implements Initializable {
#FXML
private AnchorPane anchorPane;
#FXML
private Button menu;
#FXML
private AnchorPane navList;
private double shadowSize = 15;
#Override
public void initialize(URL url, ResourceBundle rb) {
Rectangle rectangle = new Rectangle(500,500);
anchorPane.setClip(rectangle);
anchorPane.getChildren().add(setupShadowPane());
prepareSlideMenuAnimation();
}
private Pane setupShadowPane() {
Pane shadowPane = new Pane();
shadowPane.setPrefHeight(500);
shadowPane.setPrefWidth(500);
shadowPane.setStyle(
"-fx-background-color: RED;" +
"-fx-effect: dropshadow(gaussian, black, " + 20 + ", 0, 0, 0);" +
"-fx-background-insets: " + shadowSize + ";"
);
Rectangle innerBounds = new Rectangle();
Rectangle outerBounds = new Rectangle();
shadowPane.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
System.out.println(newBounds.getWidth());
innerBounds.relocate(newBounds.getMinX() + shadowSize, newBounds.getMinY() + shadowSize);
innerBounds.setWidth(newBounds.getWidth() - shadowSize * 2);
innerBounds.setHeight(newBounds.getHeight() - shadowSize * 2);
outerBounds.setWidth(newBounds.getWidth());
outerBounds.setHeight(newBounds.getHeight());
Shape clip = Shape.subtract(outerBounds, innerBounds);
shadowPane.setClip(clip);
});
return shadowPane;
}
private void prepareSlideMenuAnimation() {
TranslateTransition openNav=new TranslateTransition(new Duration(350), navList);
openNav.setToX(0);
TranslateTransition closeNav=new TranslateTransition(new Duration(350), navList);
menu.setOnAction((ActionEvent evt)->{
if(navList.getTranslateX()!=0){
openNav.play();
}else{
closeNav.setToX(-(navList.getWidth()));
closeNav.play();
}
});
}
}
Finally,I get it done.I think John Astralidis's answer is wrong.But thanks.The keys are:
Use a StackPane as a actual root pane,then add visual root pane and shadow pane to actual root pane as StackPane's children.Visual root pane is the need to add shadow effect pane.
Set visual root pane with chip that corps its outer layout to show shadow pane's shadow effect;
Set shadow pane with chip that corps its inner layout to show visual root pane's content.
Wishing my answer with my bad English can help somebody.I post my entire demo code below:
The starter class--FXApplication.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class FXApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
stage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(root);//
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The layout FXML file--FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<StackPane xmlns:fx="http://javafx.com/fxml/1" fx:id="pane" prefWidth="500" prefHeight="500" style="-fx-background-color: transparent;"
fx:controller="FXMLDocumentController">
<children>
<AnchorPane fx:id="anchorPane" prefWidth="500" prefHeight="500" style="-fx-background-color: WHITE;">
<children>
<ToolBar AnchorPane.topAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" minHeight="56.0" >
<Button text="menu" fx:id="menu" />
</ToolBar>
<StackPane fx:id="mainContent" style="-fx-background-color:rgba(0,0,0,0.30)" AnchorPane.bottomAnchor="0.0" AnchorPane.topAnchor="56.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" >
<children>
</children>
</StackPane>
<AnchorPane fx:id="navList" style="-fx-background-color:white" AnchorPane.topAnchor="56.0" AnchorPane.bottomAnchor="0.0" prefWidth="180.0" translateX="-180" >
<children>
<Label text="left side menu"/>
</children>
</AnchorPane>
</children>
</AnchorPane>
</children>
The controller class--FXMLDocumentController.java
import javafx.animation.TranslateTransition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.util.Duration;
import java.net.URL;
import java.util.ResourceBundle;
public class FXMLDocumentController implements Initializable {
#FXML
private AnchorPane anchorPane;
#FXML
private StackPane pane;
#FXML
private Button menu;
#FXML
private AnchorPane navList;
private double shadowSize = 10;
#Override
public void initialize(URL url, ResourceBundle rb) {
Rectangle rectangle = new Rectangle(480,480);
rectangle.relocate(10,10);
anchorPane.setClip(rectangle);
pane.getChildren().add(setupShadowPane());
prepareSlideMenuAnimation();
}
private Pane setupShadowPane() {
Pane shadowPane = new Pane();
shadowPane.setPrefHeight(500);
shadowPane.setPrefWidth(500);
shadowPane.setStyle(
"-fx-background-color: RED;" +
"-fx-effect: dropshadow(gaussian, black, " + 20 + ", 0, 0, 0);" +
"-fx-background-insets: " + shadowSize + ";"
);
Rectangle innerBounds = new Rectangle();
Rectangle outerBounds = new Rectangle();
shadowPane.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
innerBounds.relocate(newBounds.getMinX() + shadowSize, newBounds.getMinY() + shadowSize);
innerBounds.setWidth(newBounds.getWidth() - shadowSize * 2);
innerBounds.setHeight(newBounds.getHeight() - shadowSize * 2);
outerBounds.setWidth(newBounds.getWidth());
outerBounds.setHeight(newBounds.getHeight());
Shape clip = Shape.subtract(outerBounds, innerBounds);
shadowPane.setClip(clip);
});
return shadowPane;
}
private void prepareSlideMenuAnimation() {
TranslateTransition openNav=new TranslateTransition(new Duration(350), navList);
openNav.setToX(0 + shadowSize);
TranslateTransition closeNav=new TranslateTransition(new Duration(350), navList);
menu.setOnAction((ActionEvent evt)->{
if(navList.getTranslateX()!=0+shadowSize){
openNav.play();
}else{
closeNav.setToX(-(navList.getWidth())+shadowSize);
closeNav.play();
}
});
}
}
And the image below:
I have an ImageView which I have configured so that it is resized to fit its parent AnchorPane with the two following lines of code (both the AnchorPane and the image are square).
preview.fitWidthProperty().bind(previewPane.maxWidthProperty());
preview.fitHeightProperty().bind(previewPane.maxWidthProperty());
I have also set a fitWidth of 450 px in an fxml file that injects all nodes. When I create an instance of this object however it opens the preview with a width equal to that of the loaded image (2000 px) and not 450 px. The resizing functionality works as expected and it is possible to shrink it down to 450 px. I was wondering however if it is possible to make sure it opens up with a default size different from that of the width of the image but also making sure so that it grows and shrinks with its parent.
I have tried setting loads of different default widths in both java code and fxml but the only thing that seems to work is unbinding the fitWidth which I don't want.
Do you have any suggestions as to how I might solve this?
Main:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class MainTest extends Application {
#FXML private AnchorPane previewPane;
#FXML private ImageView preview;
#Override
public void start(Stage primaryStage) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Test.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setClassLoader(getClass().getClassLoader());
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
preview.fitWidthProperty().bind(previewPane.maxWidthProperty());
preview.fitHeightProperty().bind(previewPane.maxWidthProperty());
Scene scene = new Scene(previewPane);
primaryStage.setTitle("Test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="previewPane" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fx:id="preview" fitHeight="450.0" fitWidth="450.0" layoutX="55.0" layoutY="36.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<image>
<Image url="#Blue%20Eyes%20White%20Dragon.png" />
</image>
</ImageView>
</children>
</AnchorPane>
EDIT: Here is a MCVE of my problem.
The structure of your project is wrong. Also, to fix the problem you are having, you need to set the Scene size.
Code to get the ImageView from the Controller
//Code in the Main
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
ImageView preView = fXMLDocumentController.getPreview();
//Code in the Controller
public ImageView getPreview()
{
return preview;
}
Code to set the Scene's size
stage.setWidth(450);
stage.setHeight(450);
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication213 extends Application
{
#Override
public void start(Stage stage) throws Exception
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
ImageView preView = fXMLDocumentController.getPreview();
Scene scene = new Scene(root);
stage.setWidth(450);
stage.setHeight(450);
stage.setScene(scene);
stage.show();
preView.fitHeightProperty().bind(stage.heightProperty());
preView.fitWidthProperty().bind(stage.widthProperty());
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
#FXML
private ImageView preview;
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
public ImageView getPreview()
{
return preview;
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="previewPane" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication213.FXMLDocumentController">
<children>
<ImageView fx:id="preview" fitHeight="450.0" fitWidth="450.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<image>
<Image url="#Blue%20Eyes%20White%20Dragon.png" />
</image>
</ImageView>
</children>
</AnchorPane>
Finally, you need to uncheck Preserve Ratio. The FXML should already have this unchecked. I am pointing this out because it's important.
I'm currently programming a game called Farkle. I want to add a OnMouseClick Event for each rectangle that represent a dice.
My problem is that the rectangle doesn't recognize the MouseEvent. I built my GUI with the Scene Builder. This is an extract of my FXML Code:
<Rectangle fx:id="recDice1" arcHeight="5.0" arcWidth="5.0" fill="WHITE"
height="40.0" onMouseClicked="#recDice1_OnMouseClicked" stroke="BLACK"
strokeType="INSIDE" width="40.0" GridPane.halignment="CENTER"
GridPane.valignment="CENTER" />
The Rectangle is in a GridPane and the GridPane is ordered on the left side of a BorderPane.
And this is the extract of my Java code:
#FXML private Rectangle recDice1;
#FXML public void recDice1_OnMouseClicked(MouseEvent event){
System.out.println("Funktioniert!");
}
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Farkle");
initLayout();
}
public void initLayout(){
try {
//Erstelle FXMLLoader
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../gui/FarkleGUI.fxml"));
loader.setController(new FarkleControl());
rootLayout = (BorderPane) loader.load();
//Lade Szene
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
//Setze Grösse der Stage (Somit entfallen Margins)
primaryStage.sizeToScene();
//Zeige Szene
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
Imports:
package java2.farkle.mlz.control;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
Like I said at the beginning the rectangle doesn't recognize the MouseEvent. I tried the same with a Button and it worked fine.
Here is something you can analyze.
Main:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class Farkle 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();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.shape.Rectangle?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="farkle.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="128.0" layoutY="155.0" onAction="#handleOnButtonAction" text="Click Me!" />
<GridPane layoutX="6.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="100.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Rectangle fx:id="recDice1" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="100.0" onMouseClicked="#handleOnMouseClicked" stroke="BLACK" strokeType="INSIDE" width="160.0" />
<Rectangle fx:id="recDice2" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="100.0" onMouseClicked="#handleOnMouseClicked" stroke="BLACK" strokeType="INSIDE" width="160.0" GridPane.columnIndex="1" />
</children>
</GridPane>
</children>
</AnchorPane>
Controller:
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Rectangle;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
#FXML
private void handleOnButtonAction(ActionEvent event)
{
System.out.println("You clicked button: " + ((Button)event.getSource()).getId());
}
#FXML private void handleOnMouseClicked(MouseEvent event)
{
System.out.println("You clicked rectangle: " + ((Rectangle)event.getSource()).getId());
}
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
}
im devlop javaFx login app from tutorial on youtube for school homework. but after click login button. the login function can't show window main scene (AdminLayout.fxml). just login window hide. Thank you
this is my Error
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
... 45 more
Caused by: java.lang.NullPointerException
at mpn.manda.controller.LoginLayoutController.Login(LoginLayoutController.java:58)
... 55 more
line 58 at LoginLayoutController.java
Pane p = fxmlLoader.load(getClass().getResource("view/AdminLayout.fxml").openStream());
File LoginLayoutController.java
package mpn.manda.controller;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import mpn.manda.model.LoginModel;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* #author Xaxxis
*/
public class LoginLayoutController implements Initializable {
public LoginModel loginModel = new LoginModel();
#FXML
private Label isConnected;
#FXML
private TextField usernameField;
#FXML
private PasswordField passwordField;
#Override
public void initialize(URL location, ResourceBundle resource) {
if (loginModel.isDbConnected()) {
isConnected.setText("Connected");
} else {
isConnected.setText("Not Connected");
}
}
public void Login (ActionEvent event) {
try {
if (loginModel.isLogin(usernameField.getText(), passwordField.getText())) {
((Node)event.getSource()).getScene().getWindow().hide();
Stage primaryStage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("view/AdminLayout.fxml").openStream());
AdminLayoutController adminController = (AdminLayoutController)fxmlLoader.getController();
adminController.GetUser(usernameField.getText());
Scene scene = new Scene(p);
scene.getStylesheets().add(getClass().getResource("css/application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} else {
isConnected.setText("Username and password is not correct");
}
} catch (SQLException e) {
isConnected.setText("Username and password is not correct");
}
catch(IOException e) {
e.printStackTrace();
}
}
}
MainApp.java
package mpn.manda;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author Xaxxis
*/
public class MainApp extends Application {
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("view/LoginLayout.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("css/application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
</pre>
AdminLayoutController.java
<pre>
package mpn.manda.controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
/**
* FXML Controller class
*
* #author Xaxxis
*/
public class AdminLayoutController implements Initializable {
#FXML
private Label userLabel;
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
public void GetUser(String user) {
// TODO
userLabel.setText(user);
}
public void Logout(ActionEvent event) {
}
}
LoginLayout.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.URL?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.paint.RadialGradient?>
<?import javafx.scene.paint.Stop?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="mpn.manda.controller.LoginLayoutController">
<stylesheets>
<URL value="#/mpn/manda/css/application.css" />
</stylesheets>
<children>
<Label fx:id="isConnected" layoutX="18.0" layoutY="94.0" prefHeight="28.0" prefWidth="485.0" text="Status" textFill="#f20202">
<font>
<Font size="15.0" />
</font>
</Label>
<Label layoutX="94.0" layoutY="135.0" text="Username" />
<Label layoutX="94.0" layoutY="183.0" text="Password" />
<TextField fx:id="usernameField" layoutX="203.0" layoutY="130.0" promptText="Your username" />
<PasswordField fx:id="passwordField" layoutX="203.0" layoutY="178.0" promptText="Your password" />
<Button layoutX="203.0" layoutY="236.0" mnemonicParsing="false" onAction="#Login" prefHeight="27.0" prefWidth="78.0" text="Login..." />
<Button layoutX="288.0" layoutY="236.0" mnemonicParsing="false" prefHeight="27.0" prefWidth="78.0" text="Cancel" />
<Label layoutX="47.0" layoutY="24.0" prefHeight="59.0" prefWidth="381.0" text="Welcom To The App">
<font>
<Font size="31.0" />
</font>
<textFill>
<RadialGradient centerX="0.5" centerY="0.5" radius="0.5">
<stops>
<Stop color="#3c361c" />
<Stop color="#9a8d8d" offset="0.9330855018587361" />
<Stop color="#9a8d8d" offset="1.0" />
</stops>
</RadialGradient>
</textFill>
</Label>
</children>
</AnchorPane>
AdminLayout.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="mpn.manda.controller.AdminLayoutController">
<top>
<Label fx:id="userLabel" prefHeight="17.0" prefWidth="154.0" text="Halo, " BorderPane.alignment="CENTER" />
</top>
<bottom>
<Button mnemonicParsing="false" text="Logout.." BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
The path is wrong.
getClass().getResource("view/AdminLayout.fxml")
will resolve the path relative to the current class (so it is looking for /mpn/manda/controller/view/AdminLayout.fxml). Assuming (since the resource works correctly in MainApp) the view package is mpn.manda.view (i.e. AdminLayout.fxml and LoginLayout.fxml are in the same package), you can either do
getClass().getResource("/mpn/manda/view/AdminLayout.fxml")
(note the leading /, which resolves relative to the classpath), or
MainApp.class.getResource("view/AdminLayout.fxml")
which will resolve the path relative to the MainApp class.
Do not be tempted to use .. to reference a "parent package": this might work when you are reading resources and classes from the file system (e.g. during development), but will fail if your application is bundled in a jar file (which it will be at production time).
As an aside, you should prefer loading the FXML by specifying the URL of the FXML resource, instead of the stream. This is because any resource resolutions in the FXML file itself will fail if you do not specify a URL to the FXMLLoader. So I recommend
FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("view/AdminLayout.fxml"));
Pane p = fxmlLoader.load();
// ...
If you like the structure where you have one package (view) for the FXML files and one (controller) for the controllers (I don't, FWIW), another technique you might like is to define an empty class for the purpose of resolving view resources:
package mpn.manda.view ;
public abstract class View { }
And now you can load any FXML from anywhere with
FXMLLoader loader = new FXMLLoader(View.class.getResource("LoginLayout.fxml"));
Parent root = loader.load();
and
FXMLLoader loader = new FXMLLoader(View.class.getResource("AdminLayout.fxml"));
Parent p = loader.load();
etc. etc.
I'm trying to integrate a Digital Clock in a label, in a FXML controller, but it doesnt work, it doesnt'update, only show the original text of the label ( dunno )
Fxml:
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="320.0" prefWidth="480.0" style="-fx-background-color: SteelBlue;" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="simulazione.esame.ControllerPannello">
<children>
<Label fx:id="orario" layoutX="32.0" layoutY="65.0" prefHeight="25.0" prefWidth="247.0" text="dunno" />
<ChoiceBox fx:id="settimana" layoutX="14.0" layoutY="116.0" prefWidth="150.0" />
<Label layoutX="195.0" layoutY="108.0" text="Stato Impianto" />
<RadioButton fx:id="onRadio" layoutX="207.0" layoutY="129.0" mnemonicParsing="false" text="on" />
<RadioButton fx:id="offRadio" layoutX="263.0" layoutY="129.0" mnemonicParsing="false" text="off" />
<AnchorPane layoutX="181.0" layoutY="180.0" prefHeight="135.0" prefWidth="289.0">
<children>
<Label layoutX="14.0" layoutY="23.0" text="Temp per raffreddamento" />
<Label layoutX="14.0" layoutY="74.0" text="Temp per riscaldamento" />
<TextField layoutX="176.0" layoutY="19.0" prefHeight="25.0" prefWidth="79.0" />
<TextField layoutX="176.0" layoutY="70.0" prefHeight="25.0" prefWidth="79.0" />
</children>
</AnchorPane>
</children>
</AnchorPane>
Fxml controller:
import java.net.URL;
import java.util.Calendar;
import java.util.ResourceBundle;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.util.Duration;
/**
*
* #author Antonio
*/
public class ControllerPannello implements Initializable {
#FXML
private ChoiceBox settimana;
#FXML
private Label orario, boh;
#FXML
private RadioButton onRadio, offRadio;
private ObservableList<String> sett =
FXCollections.<String>observableArrayList("Lunedì", "Martedì", "Mercoledì",
"Giovedì", "Venerdì", "Sabato", "Domenica");
ToggleGroup stato = new ToggleGroup();
#FXML
private void handleButtonAction(ActionEvent event) {
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
onRadio.setToggleGroup(stato);
offRadio.setToggleGroup(stato);
settimana.setItems(sett);
orario = new DigitalClock();
}
}
DigitalClock.java
import java.io.IOException;
import java.net.URL;
import javafx.animation.*;
import javafx.event.*;
import javafx.scene.control.Label;
import javafx.util.Duration;
import java.util.Calendar;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
class DigitalClock extends Label {
public DigitalClock() {
bindToTime();
}
// the digital clock updates once a second.
public void bindToTime() {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
Calendar time = Calendar.getInstance();
String hourString = StringUtilities.pad(2, ' ', time.get(Calendar.HOUR) == 0 ? "12" : time.get(Calendar.HOUR) + "");
String minuteString = StringUtilities.pad(2, '0', time.get(Calendar.MINUTE) + "");
String secondString = StringUtilities.pad(2, '0', time.get(Calendar.SECOND) + "");
String ampmString = time.get(Calendar.AM_PM) == Calendar.AM ? "AM" : "PM";
setText(hourString + ":" + minuteString + ":" + secondString + " " + ampmString);
}
}
),
new KeyFrame(Duration.seconds(1))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
}
class StringUtilities {
/**
* Creates a string left padded to the specified width with the supplied padding character.
* #param fieldWidth the length of the resultant padded string.
* #param padChar a character to use for padding the string.
* #param s the string to be padded.
* #return the padded string.
*/
public static String pad(int fieldWidth, char padChar, String s) {
StringBuilder sb = new StringBuilder();
for (int i = s.length(); i < fieldWidth; i++) {
sb.append(padChar);
}
sb.append(s);
return sb.toString();
}
}