I'm making some kind of information application about a city which I need to use a database for, I got my database set up and ready and most of the code needed as well; the only part is to extract the data I need from my SQL server into a BarChart in fxml. Can anyone give me a example or something?
My fxml:
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controllers.ControllerZW">
<BarChart fx:id="graph" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</BarChart>
</Pane>
My controller atm:
package Controllers;
public class ControllerZW implements Interface.Ibacktomenu {
#Override
public void backtomenu() {
try {
Main.mainStage.setScene(
new Scene(FXMLLoader.load(getClass().getResource("../scenes/MainMenu.fxml")))
);
} catch (IOException e) {
System.out.println("Probably couldnt find resource file");
e.printStackTrace();
}
}
}
Do you want to render the data form database to XML format?
I think some template engine maybe help you, such as Freemarker.
You could use Freemarker as view of Spring MVC, please refer to http://viralpatel.net/blogs/spring-mvc-freemarker-ftl-example/
Use a Task to get the data from the database and any method described in Passing Parameters JavaFX FXML to get the data to the controller, e.g.
#Override
public void start(Stage primaryStage) {
Task<Pane> dataLoader = new Task<Pane>() {
#Override
protected Pane call() throws Exception {
// create data
XYChart.Series<String, Double> rain = new XYChart.Series<>();
rain.setName("rain");
Month[] months = Month.values();
for (Month month : months) {
// simulates slow database connection; just adding some random values here
Thread.sleep(200);
rain.getData().add(new XYChart.Data<>(month.toString(), Math.random() * 100));
}
// load chart (replace BarChartLoad.class.getResource("chart.fxml") with your own URL)
FXMLLoader loader = new FXMLLoader(BarChartLoad.class.getResource("chart.fxml"));
Pane pane = loader.load();
// pass data to controller
loader.<ControllerZW>getController().setData(FXCollections.observableArrayList(rain));
return pane;
}
};
// placeholder
Pane root = new Pane();
Scene scene = new Scene(root, 1000, 600);
// set new scene root on successfull completion of the task
dataLoader.setOnSucceeded(evt -> scene.setRoot(dataLoader.getValue()));
// TODO: handle task failure
new Thread(dataLoader).start();
primaryStage.setScene(scene);
primaryStage.show();
}
public class ControllerZW implements Interface.Ibacktomenu {
#FXML
private BarChart<String, Double> graph;
public void setData(ObservableList<XYChart.Series<String, Double>> data) {
graph.setData(data);
}
...
Related
I want to make switching photo program, using imageView and keyEvent, but when I try to use keyEvent it dosen't work, I was trying add scene.getRoot().requestFocus(); but didn't help, so my question is, why it dosen't work any how could I activate it?
MenuScreenController.java
#FXML
public void getNewImageHandler(KeyEvent event) {
System.out.println(singleFile.getName());
imgFieldView.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.N) {
photoSwipCounter++;
System.out.println("P clicked");
} else if (e.getCode() == KeyCode.P) {
photoSwipCounter--;
}
});
// if (event.getCode().equals(KeyCode.N)) {
// photoSwipCounter++;
// }
// if (event.getCode().equals(KeyCode.P)) {
// photoSwipCounter--;
// }
if (photoSwipCounter < 0) {
singleFile = selectedImgsList.get(selectedImgsList.size() - photoSwipCounter);
} else {
singleFile = selectedImgsList.get(photoSwipCounter);
}
image = new Image(singleFile.toURI().toString(),
900, 400,
true, true, true);
imgFieldView.setImage(image);
}
As you can see I was trying many methods, by stream, or classic, but it dosen't make change.
MenuScreen.fxml
<Pane fx:id="menuPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="screensaverfxml.Controllers.MenuScreenController">
<children>
<ImageView fx:id="imgFieldView" fitHeight="400.0" fitWidth="900.0" layoutX="66.0" layoutY="62.0" onKeyPressed="#getNewImageHandler" onMouseClicked="#imgDoubleClick" pickOnBounds="true" preserveRatio="true" />
</children>
</Pane>
ScreenSaverFXML.java
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/screensaverfxml/fxmlConfig/MainScreen.fxml"));
Pane mainPane = loader.load();
Scene scene = new Scene(mainPane, 1000, 700);
primaryStage.setScene(scene);
primaryStage.setTitle("Screen Saver");
primaryStage.show();
scene.getRoot().requestFocus();
}
And ofc I have method to load first photo on imageView and it's work by load it from the folder to the list, but switching to next nope
Only nodes that have the focus receive key events. Since you have scene.getRoot().requestFocus() it's the root that receives the events. However, you're adding your EventHandler to imgFieldView and since that node is a descendant of the root it never sees any key events. You need to either have your imgFieldView obtain the focus or add your handler to the root node instead.
Note: You can only request focus once the target Node is part of a Scene.
The other problem is your call to imgFieldView.setOnKeyPressed(...) in the getNewImageHandler method. When you add an event handler via FXML, for instance by using onKeyPressed="#getNewImageHandler", it sets the corresponding onXXX property of the node. In your case, it's setting the onKeyPressed property of imgFieldView. However, in that handler you also set that property which replaces the handler set by the FXMLLoader. Your new handler simply increments or decrements the photoSwipeCounter field but does nothing with the new value. Your method should look more like:
#FXML
public void getNewImageHandler(KeyEvent event) {
if (event.getCode().equals(KeyCode.N)) {
photoSwipeCounter++;
}
if (event.getCode().equals(KeyCode.P)) {
photoSwipeCounter--;
}
// wrap around logic
if (photoSwipeCounter < 0) {
photoSwipeCounter = selectedImgsList.size() - 1;
} else if (photoSwipeCounter >= selectedImgsList.size()) {
photoSwipeCounter = 0;
}
singleFile = selectedImgsList.get(photoSwipeCounter);
image = new Image(singleFile.toURI().toString(),
900, 400,
true, true, true);
imgFieldView.setImage(image);
}
I would like to add a custom element into a VBox.
For example: being able to write VBox.getChildren().add(element) and element is a custom node created by me in FXML.
I already followed this tutorial: https://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
but the example only shows how to do this inside the same controller (a single controller, i already have my "big" controller, which is WinnerController, I would like to split the two classes, one that manages the single element, and one that manages the whole scene Winner.fxml).
I already have a class WinnerController which is the controller of my FXML Winner.fxml.
Here the code of my Winner.fxml:
<AnchorPane id="paneWinner" fx:id="paneWinner" prefHeight="800.0" prefWidth="1280.0" stylesheets="#winner.css" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.gui.WinnerController">
<children>
<VBox layoutX="434.0" layoutY="125.0" prefHeight="250.0" prefWidth="413.0" spacing="10.0">
<children>
<AnchorPane id="leaderBoardElement" prefHeight="80.0" prefWidth="413.0" stylesheets="#leaderBoard.css">
<children>
<Text layoutX="49.0" layoutY="45.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="107.13671875" />
</children></AnchorPane>
</children>
</VBox>
I would like to dynamically add element with the id "leaderBoardElement" (so an AnchorPane + Text) into my VBox.
How can i do that?
Edit: I also tried with this solution:How to understand and use `<fx:root>` , in JavaFX?
but i keep getting nothing. When i do vbox.getChildren().add(new MyComponent());
called in my WinnerControlleri get nothing.
WinnerController class:
public class WinnerController implements Initializable {
#FXML
private VBox leaderBoard;
#FXML
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Winner Init");
MyComponent test = new MyComponent();
System.out.println(test);
// leaderBoard.getChildren().add(new MyComponent());
}
}
My Component class:
public class MyComponent extends AnchorPane {
#FXML
private TextField textField ;
#FXML
private Button button ;
public MyComponent() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyComponent.fxml"));
loader.setController(this);
loader.setRoot(this);
loader.load();
textField.setText("HELLO!");
} catch (IOException exc) {
// handle exception
System.out.println("ELEMENT NOT CREATE!!!");
}
}
}
Winner.fxml:
<AnchorPane id="paneWinner" fx:id="paneWinner" prefHeight="800.0"
prefWidth="1280.0" stylesheets="#winner.css" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.gui.WinnerController">
<children>
<VBox fx:id="leaderBoard" layoutX="434.0" layoutY="125.0" prefHeight="250.0" prefWidth="413.0" spacing="10.0" />
MyComponent.fxml:
<fx:root type="javafx.scene.layout.AnchorPane" fx:id="leaderBoardElement" id="leaderBoardElement">
<TextField fx:id="textField" />
<Button fx:id="button" />
And i call the creation and loading of Winner.fxml from another class like this:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/Winner.fxml"));
if (loader!=null)
System.out.println("LOADER NOT NULL!!");
try{
System.out.println("TRY!");
Parent root = (Parent) loader.load();
if(root!=null)
System.out.println("ROOT NOT NULL!!");
Scene startedGame = new Scene(root, 1280, 800, Color.WHITE);
if(startedGame!=null)
System.out.println("SCENE NOT NULL!");
Stage window = (Stage) paneCarta0.getScene().getWindow();
if (window!=null)
System.out.println("WINDOW NOT NULL!!");
window.setScene(startedGame);
window.show();
catch (IOException Exception) {
System.out.println("View not found. Error while loading");
}
The problem is inside the new MyComponent(), where probably i get an exception and it propagates to my main caller. I've tried everything but i can't figure out why it can't create the MyComponent object.
If your custom component is in a separate FXML file you can do this.
In your WinnerController class:
#FXML
private void initialize() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getRessource("customElement.fxml"));
fxmlLoader.setController(new CustomElementController()); //Or just specify the Controller in the FXML file
myVBox.getChildren().add(fxmlLoader.load());
}
Edit: In this solution there should be NO <fx:include> tags in your main fxml
In my JavaFX application I have to load many fxml files (200+) in the same time. I have decided to load them in background Task just like in https://stackoverflow.com/a/34878843 answear. Everything works fine (load time was acceptable) until JDK update. Newest version of JDK lengthened load time 3-4 times.
I have checked previous JDK releases and that problem appears from the JDK 8u92.
To test that issue I created new simple JavaFX FXML Application in Netbeans 8.1 and use only generated classes and fxml. Creating view from code works fine.
Application class:
public class FXMLLoaderTest extends Application {
private static Executor ex = Executors.newCachedThreadPool();
//private static Executor ex = Executors.newFixedThreadPool(400);
//private static Executor ex = Executors.newSingleThreadExecutor();
#Override
public void start(Stage stage) throws Exception {
VBox box = new VBox();
ScrollPane root = new ScrollPane(box);
Button b = new Button("GENERATE");
b.setOnAction(e -> {
IntStream.range(0, 1000).forEach(i -> {
Task<Parent> task = new Task<Parent>() {
#Override
protected Parent call() throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = null;
try {
root = loader.load();
} catch (IOException ex) {
Logger.getLogger(Loader.class.getName()).log(Level.SEVERE, null, ex);
}
// StackPane root= new StackPane();
// Button click = new Button("Click");
// root.setPrefSize(300, 300);
// root.getChildren().add(click);
return root;
}
};
task.setOnSucceeded(ev -> {
final Parent parent = task.getValue();
box.getChildren().add(parent);
});
task.setOnFailed(ev -> task.getException().printStackTrace());
ex.execute(task);
});
});
box.getChildren().add(b);
Scene scene = new Scene(root, 400, 500);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXMLDocument.fxml
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmlloader.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
FXMLDocumentController.java
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
I have tested this on several computers and result was always the same. On JDK 8u91 fxml files load fast. I have checked release note of 8u92 and I haven't found any changes in FXMLLoader class.
Has anybody encounter this issue? Mayby I am doing something wrong then please correct me.
I've got the following classes:
Main:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = FXMLLoader.load(getClass().getResource("../view/PersonOverview.fxml"));
AnchorPane view2 = FXMLLoader.load(getClass().getResource("../view/view2.fxml"));
root.setLeft(view2);
primaryStage.setScene(new Scene(root, 1000, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
TreeController:
public class TreeController implements Initializable {
//Set icon for folder
Node folderIcon = new ImageView(new Image(this.getClass().getResourceAsStream("../icon/icon.jpg")));
//Set root
TreeItem<String> root;
#FXML TreeView<String> tree;
//Set other Items
private TreeItem<String> item1 = new TreeItem<String>("item1", folderIcon);
private TreeItem<String> item2 = new TreeItem<String>("item2", folderIcon);
private TreeItem<String> item3 = new TreeItem<String>("item3", folderIcon);
private TreeItem<String> item4 = new TreeItem<String>("item4", folderIcon);
private TreeItem<String> item5 = new TreeItem<String>("item5", folderIcon);
//Add Children to root
private void makeChildren() {
root.getChildren().add(item1);
root.getChildren().add(item2);
root.getChildren().add(item3);
root.getChildren().add(item4);
root.getChildren().add(item5);
}
#Override
public void initialize(URL location, ResourceBundle resources) {
root = new TreeItem<String>("root", folderIcon);
makeChildren();
root.setExpanded(true);
tree.setRoot(root);
}
}
And of course my view2 fxml file:
<AnchorPane
maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="354.0"
xmlns="http://javafx.com/javafx/8.0.40"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="control.TreeController">
<children>
<TreeView
layoutX="69.0" layoutY="118.0"
prefHeight="400.0" prefWidth="354.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
Now the problem I have is that it will throw a Nullpointer Exception at tree.setRoot(root);
And a ConstructLoad Exception in my Main at:
AnchorPane view2 = FXMLLoader.load(getClass().getResource("../view/view2.fxml"));
I'm still learning this stuff but I was told that when using FXML, you don't need to initialize TreeViews using "new" as the #FXML annotation will already take care of this with tree.setRoot(root).
Sorry for such a noobish question but I've been googling for the past 2 hours and haven't gotten any wiser.
I'm still learning this stuff but I was told that when using FXML, you don't need to initialize TreeViews using "new" as the #FXML annotation will already take care of this with tree.setRoot(root).
You guessed right, but in order for JavaFX to inject your Treeview (= make the "new" for you) you need to declare something like:
<Treeview fx:id="tree" />
in view2.fxml.
With the fx:id attribute setted to the same name as your Treeview variable in Java code.
Here is my Main java file.The probelm is that the Whole project is working on double click when i launch it.
public Stage primaryStage;
public BorderPane rootLayout;
private Pane splashLayout;
private ProgressBar loadProgress;
private Label progressText;
private static final int SPLASH_WIDTH = 600;
private static final int SPLASH_HEIGHT = 400;
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(final Stage initStage) throws Exception {
//this.primaryStage = primaryStage;
FXMLLoader fxmlLoader1 = new FXMLLoader(getClass().getResource(
"KDAF_Splash.fxml"));
try {
// flag = false;
Parent root2 = fxmlLoader1.load();
Stage stage2 = new Stage();
stage2.initStyle(StageStyle.TRANSPARENT);
// masterpane = new Pane();
// masterpane.setOpacity(1);
// stage2.setTitle("Create New Project");
stage2.setScene(new Scene(root2, 600, 400));
stage2.show();
PauseTransition delay = new PauseTransition(Duration.seconds(5));
delay.setOnFinished( event ->{ stage2.close();showMainStage();} );
delay.play();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
};
private void showMainStage(
) {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Preloader.class.getResource("RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Stage stage=new Stage();
stage.setTitle("Activation");
Scene scene = new Scene(rootLayout);
//stage.initStyle(StageStyle.DECORATED);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
showPersonOverview();
//mainStage.show();
/* mainStage.setTitle("Activation Wizard");
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
// primaryStage.initStyle(StageStyle.UTILITY);
mainStage.setResizable(false);
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setScene(scene);
mainStage.show();
showPersonOverview();*/
} catch (IOException e) {
e.printStackTrace();
}
}
public void showPersonOverview() {
try {
// Load person overview.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("activation wizard.fxml"));
AnchorPane personOverview = (AnchorPane) loader.load();
personOverview.setPrefHeight(400);
// Set person overview into the center of root layout.
rootLayout.setCenter(personOverview);
} catch (IOException e) {
e.printStackTrace();
}
}
private void showSplash(
final Stage initStage,
Task<?> task,
InitCompletionHandler initCompletionHandler
) {
progressText.textProperty().bind(task.messageProperty());
loadProgress.progressProperty().bind(task.progressProperty());
task.stateProperty().addListener((observableValue, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
loadProgress.progressProperty().unbind();
loadProgress.setProgress(1);
initStage.toFront();
FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2), splashLayout);
fadeSplash.setFromValue(1.0);
fadeSplash.setToValue(0.0);
fadeSplash.setOnFinished(actionEvent -> initStage.hide());
fadeSplash.play();
initCompletionHandler.complete();
} // todo add code to gracefully handle other task states.
});
Scene splashScene = new Scene(splashLayout);
initStage.initStyle(StageStyle.UNDECORATED);
final Rectangle2D bounds = Screen.getPrimary().getBounds();
initStage.setScene(splashScene);
initStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
initStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);
initStage.show();
}
public interface InitCompletionHandler {
public void complete();
}
}
The FXml is given below. Please help me to resolve this issue. If the question is not clear help me to explain better. The main problem is when the application is launched after splash screen. The button accepts double click and then moves to load next FXML. this is been very painful as i have to double click everytime instead of single click. I am not able to identify the problem here. Whether it is a problem that persists from scene builder or the problem is in the main preloader class.Even the menu item is accepting double click. I try to google the solution for but could not find any solution. please look int the code and help to resolve this issue. I have done a lot of R&D but all went vain . There might be a little problem in it but i am not being able to identify it. Please ignore the formatting of code and unused variables. The code is not final yet. finally i would like to remind the main problem is that after launching, the application is working only on double click. lets look at the work flow to understand it better. SPLASH SCREEN->ACTIVATION WIZARD-DOUBLE CLICK ON A BUTTON->TIP SCREEN-DOUBLE CLICK ON A BUTTON->PROJECT SCREEN->DOUBLE CLICK TO OPEN ANYTHING. It is really frustrating. please help.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-border-color: black;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="EventHandlingController">
<children>
<Button layoutX="301.0" layoutY="333.0" mnemonicParsing="false" text="Buy Full Version" />
<Button fx:id="myButton7" layoutX="420.0" layoutY="333.0" mnemonicParsing="false" onAction="#Showtip" prefHeight="25.0" prefWidth="114.0" text="Continue Trial " />
<TextField editable="false" layoutX="85.0" layoutY="108.0" prefHeight="151.0" prefWidth="449.0" style="-fx-background-color: silver;" text="You have <xx> days left on your trial.">
<font>
<Font size="21.0" />
</font>
</TextField>
<Label layoutX="85.0" layoutY="23.0" prefHeight="37.0" prefWidth="135.0" text="Activation Wizard">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Button fx:id="closebutt" layoutX="573.0" layoutY="2.0" mnemonicParsing="false" onAction="#closebuttonD" prefHeight="15.0" prefWidth="20.0" text="X" />
</children>
</AnchorPane>