I am programming a Music Player with JavaFX and Scene Builder.
My problem is, that if I resize the Window of my program, the UI does not grow with it. How to make the UI responsive?
Before I added the SplashScreen, it worked fine.
Since then I tried to get it to work, but I can't find any solution on the web!
Please help me, thanks in advance!
Main:
package sample;
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 {
public static boolean isSplashLoaded = false;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Juggle v0.1");
primaryStage.setScene(new Scene(root, 1024, 640));
primaryStage.setResizable(true);
primaryStage.show();
}
}
Controller:
package sample;
import javafx.animation.FadeTransition;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable{
public MenuItem openFile;
public BorderPane parent;
public void openFile(){
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open File...");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Audio Files", "*.wav", "*.mp3"));
File f = fileChooser.showOpenDialog(parent.getScene().getWindow());
if ( f != null) {
Media pick = new Media(f.toURI().toString());
MediaPlayer player = new MediaPlayer(pick);
MediaView view = new MediaView(player);
parent.getChildren().add(view);
player.play();
}
else{
}
}
public void loadSplashScreen() throws IOException {
Main.isSplashLoaded = true;
BorderPane pane = FXMLLoader.load(getClass().getResource("Splash.fxml"));
parent.getChildren().setAll(pane);
FadeTransition fadeIn = new FadeTransition(Duration.seconds(3), pane);
fadeIn.setFromValue(0);
fadeIn.setToValue(1);
fadeIn.setCycleCount(1);
FadeTransition fadeOut = new FadeTransition(Duration.seconds(3), pane);
fadeOut.setFromValue(1);
fadeOut.setToValue(0);
fadeOut.setCycleCount(1);
fadeIn.play();
fadeIn.setOnFinished((e) ->{
fadeOut.play();
});
fadeOut.setOnFinished((e) -> {
try {
BorderPane parentContent = FXMLLoader.load(getClass().getResource("sample.fxml"));
parent.getChildren().setAll(parentContent);
} catch (IOException e1) {
e1.printStackTrace();
}
});
}
#Override
public void initialize(URL location, ResourceBundle resources) {
if(!Main.isSplashLoaded){
try {
if(!Main.isSplashLoaded){
loadSplashScreen();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<BorderPane BorderPane.alignment="CENTER" fx:id="parent"
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="640.0" prefWidth="1024.0"
style="-fx-background-color: #93F979;"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="sample.Controller">
<bottom>
<BorderPane prefHeight="93.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<top>
<HBox alignment="TOP_CENTER" prefHeight="32.0" prefWidth="800.0" BorderPane.alignment="TOP_CENTER">
<children>
<Label alignment="CENTER" prefHeight="17.0" prefWidth="50.0" text="00:00" textAlignment="CENTER" />
<ProgressBar prefHeight="10.0" prefWidth="900.0" progress="0.0">
<HBox.margin>
<Insets top="4.0" />
</HBox.margin></ProgressBar>
<Label alignment="CENTER" prefHeight="17.0" prefWidth="50.0" text="00:00" textAlignment="CENTER" />
</children>
</HBox>
</top>
</BorderPane>
</bottom>
<center>
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true"
BorderPane.alignment="CENTER">
<image>
<Image url="#../Music.png" />
</image>
</ImageView>
</center>
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="openFile" mnemonicParsing="false" onAction="#openFile" text="Open..." />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
Splash FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="640.0" prefWidth="1024.0" style="-fx-background-color: #93F979;" BorderPane.alignment="CENTER" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Main">
<center>
<ImageView fitHeight="150.0" fitWidth="200.0" nodeOrientation="INHERIT" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER">
<image>
<Image url="#../Splash.png" />
</image>
</ImageView>
</center>
</BorderPane>
Use static methods of BorderPane class like this
BorderPane.setAlignment ( node , Pos.CENTER );
Did you try using VBox instead?
Related
I've realised only through clearing up code that I thought I could clear up and had cleared from some of my Controller classes where my issue is. To word my question better and provide more clarity to the concept of prioritisation I'll give a brief explanation followed by some code. Imagine an interface with a side of the screen being consistent and permanent to the interface where you have Buttons for menu-ing where you essentially move between tabs changing the rest of the Stage passing fxml files to the Pane associated.
Reading examples and questions I understood this to be viable and using the framework from this link https://gist.github.com/jewelsea/6460130 seeing a header remain consistent while switching Scene between vista1.fxml and vista2.fxml, my understanding was that if the Header remains from main.fxml as part of the scene that the Stage is therefore using either both main.fxml and vista1.fxml or main.fxml and vista2.fxml concurrently and thus both associated controllers exist and will have access to corresponding methods according to the Pane interacted with.
That is clearly not the case though and the consistent Pane in this case main.fxml does not have its controller since when the other is loaded and creates its controller it replaces or clears the other controller in some form or another I now presume is the case. I thought I could avoid code duplication by using separate Panes with the consistency of the menu bar but also being able to use its buttons.
Some code as an example:
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception{
stage.setTitle("Vista Viewer");
stage.setScene(createScene(loadMainPane()));
stage.show();
}
private Pane loadMainPane() throws IOException {
FXMLLoader loader = new FXMLLoader();
Pane mainPane = (Pane) loader.load(getClass().getResourceAsStream(
VistaNavigator.MAIN));
MainController mainController = loader.getController();
VistaNavigator.setMainController(mainController);
VistaNavigator.loadVista(VistaNavigator.VISTA_1);
return mainPane;
}
private Scene createScene(Pane mainPane) {
Scene scene = new Scene(mainPane);
return scene;
}
public static void main(String[] args) {
launch(args);
}
}
VistaNavigator.java
package sample;
import javafx.fxml.FXMLLoader;
import java.io.IOException;
public class VistaNavigator {
public static final String MAIN = "main.fxml";
public static final String VISTA_1 = "vista1.fxml";
public static final String VISTA_2 = "vista2.fxml";
public static final String OTHER_MENU_OPTION = "otherMenu.fxml";
private static MainController mainController;
public static void setMainController(MainController mainController) {
VistaNavigator.mainController = mainController;
}
public static void loadVista(String fxml) {
try {
mainController.setVista(
FXMLLoader.load(
VistaNavigator.class.getResource(
fxml
)
)
);
} catch (IOException e) {
e.printStackTrace();
}
}
}
MainController.java
package sample;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.layout.StackPane;
public class MainController {
#FXML
private StackPane vistaHolder;
public void setVista(Node node) {
vistaHolder.getChildren().setAll(node);
}
public void homebtn() throws Exception{
VistaNavigator.loadVista(VistaNavigator.VISTA_1);
}
public void otherMenuOption() throws Exception{
VistaNavigator.loadVista(VistaNavigator.OTHER_MENU_OPTION);
}
}
main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="200.0" prefWidth="300.0" xmlns:fx="http://javafx.com/fxml" fx:controller="sample.MainController">
<children>
<VBox prefWidth="155.0">
<children>
<Label fx:id="headerLabel" maxWidth="120.0" text="Header" />
</children>
</VBox>
<Pane layoutY="40.0" prefHeight="200.0" prefWidth="120.0" style="-fx-background-color: #091D34;">
<children>
<Button fx:id="button1" layoutY="60.0" mnemonicParsing="false" onAction="#homebtn" prefHeight="44.0" prefWidth="120.0" style="-fx-background-color: #133863;" text="Home" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
<Button fx:id="button2" layoutY="110.0" mnemonicParsing="false" onAction="#otherMenuOption" prefHeight="44.0" prefWidth="120.0" style="-fx-background-color: #133863;" text="OtherMenuOption" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
</children>
</Pane>
<StackPane fx:id="vistaHolder" VBox.vgrow="ALWAYS" />
</children>
</AnchorPane>
otherMenu.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 fx:id="otherMenuOption" xmlns:fx="http://javafx.com/fxml" fx:controller="sample.Vista1Controller">
<children>
<Label fx:id="label" layoutX="135.0" layoutY="57.0" maxWidth="120.0" text="other program stuff" VBox.vgrow="NEVER" />
</children>
</StackPane>
Vista1Controller.java
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
public class Vista1Controller {
#FXML
void nextPane(ActionEvent event) {
VistaNavigator.loadVista(VistaNavigator.VISTA_2);
}
}
vista1.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="sample.Vista1Controller" prefHeight="400.0" prefWidth="600.0">
<children>
<Pane fx:id="Vista1" layoutX="155.0" layoutY="-1.0" prefHeight="430.0" prefWidth="574.0" style="-fx-background-color: transparent">
<Button fx:id="btn" layoutX="135.0" layoutY="57.0" mnemonicParsing="false" onAction="#nextPane" prefHeight="149.0" prefWidth="318.0" style="-fx-background-color: #133863;" text="Open Vista2" textFill="#ffffff">
<font>
<Font name="Britannic Bold" size="20.0" />
</font>
</Button>
</Pane>
</children>
</AnchorPane>
Vista2Controller.java
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
public class Vista2Controller {
#FXML
void previousPane(ActionEvent event) {
VistaNavigator.loadVista(VistaNavigator.VISTA_1);
}
}
vista2.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="sample.Vista2Controller" prefHeight="400.0" prefWidth="600.0">
<children>
<Pane fx:id="Vista2" layoutX="155.0" layoutY="-1.0" prefHeight="430.0" prefWidth="574.0" style="-fx-background-color: transparent">
<Button fx:id="btn" layoutX="135.0" layoutY="57.0" mnemonicParsing="false" onAction="#previousPane" prefHeight="149.0" prefWidth="318.0" style="-fx-background-color: #133863;" text="Open Vista1" textFill="#ffffff">
<font>
<Font name="Britannic Bold" size="20.0" />
</font>
</Button>
</Pane>
</children>
</AnchorPane>
Is there a good way to maintain this design and prevent code duplication within the specific controllers and would it be through inheritance or passing parameters, I'm not sure what this is comparable to nor whether it's possible?
I got items on my listview roles but they are not showing in my program after running in window. Gui done in Scene Builder. When i run program field where should be items is white blank just empty.
printscreen of program
https://zapodaj.net/c60f99a10f300.jpg.html
scene builder
https://zapodaj.net/26fbf2123397c.jpg.html
When i use show sample data in Scene Builder it shows lorem ipsum etc.
here u got code from controller and fmxl document.
package sample;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import java.net.URL;
import java.util.*;
public class ControllerBindColors implements Initializable {
#FXML
private ListView<String > roles;
#FXML
private ListView<String> colors;
#FXML
private ListView<?> binded;
String selectedRole;
String selectedColor;
int numberOfPlayers;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
public void initData(int numberOfPlayers, String selectedRole, String selectedColor) {
this.numberOfPlayers = numberOfPlayers;
this.selectedRole = selectedRole;
this.selectedColor = selectedColor;
ObservableList<String> itemsRoles = FXCollections.observableArrayList("test","test2","test3");
roles = new ListView<>();
roles.setItems(itemsRoles);
roles.getItems().addAll("test555");
roles.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
System.out.println(roles.getItems());
}
}
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.ListView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox spacing="10.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ControllerBindColors">
<children>
<HBox alignment="CENTER">
<children>
<ListView fx:id="roles" prefHeight="200.0" prefWidth="200.0" />
<VBox alignment="CENTER" spacing="10.0">
<children>
<Button fx:id="backBtn" ellipsisString="BACK" mnemonicParsing="false" onAction="#back" text="BACK" />
<Label prefHeight="51.0" prefWidth="71.0" text="Select role and color then bind." textAlignment="CENTER" wrapText="true" />
<Button fx:id="bindbtn" ellipsisString="BIND" mnemonicParsing="false" onAction="#bind" text="BIND" />
<Button fx:id="nextBtn" ellipsisString="NEXT" mnemonicParsing="false" onAction="#next" text="NEXT" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</VBox>
<ListView fx:id="colors" prefHeight="200.0" prefWidth="200.0" />
</children>
</HBox>
<ListView fx:id="binded" prefHeight="200.0" prefWidth="200.0" />
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
initData
ControllerNewGame.java startGame() is called when is activaded button
#FXML
void startGame() {
try{
Parent root= FXMLLoader.load(getClass().getResource("BindColor.fxml"));
ControllerBindColors controller = new ControllerBindColors();
int number = (int)slider.getValue();
controller.initData(number,selectedRole.getText(),selectedColor.getText());
Stage toGame = (Stage)startButton.getScene().getWindow();
toGame.setTitle("Parasite Pip-Boy Bind Color Menu");
toGame.setScene(new Scene(root, 600, 300));
toGame.show();
}catch(IOException e) {
startButton.setText("Reinstall program. BindColor.fxml is missing or is corrupted. :(");
}
}
list has items for sure in console there are printed all 4 items
[test, test2, test3, test555]
To get a reference to the controller used by the FXML (instead of constructing a new one):
FXMLLoader loader = new FXMLLoader();
Parent root= loader.load(getClass().getResource("BindColor.fxml").openStream());
ControllerBindColors controller = fxmlLoader.getController();
after getting a reference to it, you can use it as you did:
controller.initData(number,selectedRole.getText(),selectedColor.getText());
I am trying to make charts, but I am stuck now. I have a document where I get challenges to do. I am new to JavaFX and I am trying to get 2 charts to work when I click a button. I have a line chart and a pie chart. The charts arent working because I dont have data in it. What I want is to click "pie chart" and the pie chart is showing and the message says "Drawing a pie chart". The pie chart wont show because there is no data, but that is not the point right now. I made the charts invisible en when I click one of the charts one will be visible and the other one invisible. This is everything I tried but it didnt work. If you didnt understand just comment and I will try to help.
Controller
package ala.javafxchart;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Label;
public class MainSceneController implements Initializable {
#FXML
private Label label;
#FXML
private PieChart pieChart;
#FXML
private LineChart lineChart;
#FXML
private void handlePieChartAction(ActionEvent event) {
System.out.println("You clicked the Pie Chart!");
label.setText("Drawing a pie chart!!");
pieChart.setVisible(true);
}
#FXML
private void handleLineChartAction(ActionEvent event) {
System.out.println("You clicked the Pie Chart!");
label.setText("Drawing a line chart!!");
lineChart.setVisible(false);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
#FXML
private void handleLineChartAction(ActionEvent event) {
System.out.println("You clicked the Pie Chart!");
label.setText("Drawing a line chart!!");
setVisible(lineChart);
}
private void setVisible(PieChart chart){
}
private void setVisible(LineChart chart){
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.chart.PieChart?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" prefHeight="768.0" prefWidth="1366.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ala.javafxchart.MainSceneController">
<children>
<BorderPane prefHeight="768.0" prefWidth="1498.0">
<top>
<Label text="Chart Demo" BorderPane.alignment="CENTER">
<font>
<Font size="35.0" />
</font>
</Label>
</top>
<left>
<VBox prefHeight="692.0" prefWidth="241.0" BorderPane.alignment="CENTER">
<children>
<Button fx:id="lineChart" mnemonicParsing="false" prefHeight="45.0" prefWidth="245.0" text="Line Chart" />
<Button fx:id="pieChart" mnemonicParsing="false" prefHeight="45.0" prefWidth="245.0" text="Pie Chart" />
</children>
</VBox>
</left>
<bottom>
<Label fx:id="statusLabel" text="status message" BorderPane.alignment="CENTER">
<padding>
<Insets right="1400.0" />
</padding>
</Label>
</bottom>
<center>
<StackPane prefHeight="150.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<LineChart title="Lost Luggage 2016" visible="false">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
<PieChart title="Lost Luggage 2016" visible="false" />
</children>
</StackPane>
</center>
</BorderPane>
</children>
</AnchorPane>
Try this I made some changes to your fxml to make it more readable
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import java.net.URL;
import java.util.ResourceBundle;
public class MainSceneController implements Initializable {
public Button lineChartButton;
public Button pieChartButton;
public LineChart lineChart;
public PieChart pieChart;
public Label label;
#FXML
private void handlePieChartAction() {
System.out.println("You clicked the Pie Chart!");
label.setText("Drawing a pie chart!!");
if(pieChart.isVisible())
pieChart.setVisible(false);
else
pieChart.setVisible(true);
}
#FXML
private void handleLineChartAction() {
System.out.println("You clicked the Line Chart!");
label.setText("Drawing a line chart!!");
if(lineChart.isVisible())
lineChart.setVisible(false);
else
lineChart.setVisible(true);
}
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO
lineChartButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
handleLineChartAction();
}
});
pieChartButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e){
handlePieChartAction();
}
});
}
}
This is the FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.chart.PieChart?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" prefHeight="768.0" prefWidth="1366.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainSceneController">
<children>
<BorderPane prefHeight="768.0" prefWidth="1498.0">
<top>
<Label text="Chart Demo" BorderPane.alignment="CENTER">
<font>
<Font size="35.0" />
</font>
</Label>
</top>
<left>
<VBox prefHeight="692.0" prefWidth="241.0" BorderPane.alignment="CENTER">
<children>
<Button fx:id="lineChartButton" mnemonicParsing="false" prefHeight="45.0" prefWidth="245.0" text="Line Chart" />
<Button fx:id="pieChartButton" mnemonicParsing="false" prefHeight="45.0" prefWidth="245.0" text="Pie Chart" />
</children>
</VBox>
</left>
<bottom>
<Label fx:id="label" text="status message" BorderPane.alignment="CENTER">
<padding>
<Insets right="1400.0" />
</padding>
</Label>
</bottom>
<center>
<StackPane prefHeight="150.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<LineChart fx:id="lineChart" title="Lost Luggage 2016" visible="false">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
<PieChart fx:id="pieChart" title="Lost Luggage 2016" visible="false" />
</children>
</StackPane>
</center>
</BorderPane>
</children>
</AnchorPane>
I renamed your buttons to lineChartButton and pieChartButton instead of lineChart and pieChart because thats super confusing and gave ids to the pieChart and lineChart
I have tabpane and depending upon what is going on I'd like to make certain tabs invisible and others visible. The scene and tabs are all defined in FXML.
I know I can use:
tabPane.getTabs().add(0, tab1);
and
tabPane.getTabs().remove(tab1);
but all my tabs, including tab1 are defined in FXML. If I could get and save all the defined tabs and save them so I could re-add them later that would be OK.
Your solution above is fine. Just make sure that in your FXML you give an ID to each tab you want to manipulate.
<Tab fx:id="myTab1">....</Tab>
For this example I used the closing policy of the tab control to remove tabs from the scene. But this should give you enough information to start with. Here is a working solution that might point you in the right direction:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="250.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.TestController">
<children>
<TabPane fx:id="tabPane" layoutX="14.0" layoutY="14.0" prefHeight="294.0" prefWidth="446.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab fx:id="tab1" text="Tab 1">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="tab2" text="Tab 2">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="tab3" text="Tab 3">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="tab4" text="Tab 4">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
</TabPane>
<ButtonBar layoutX="138.0" layoutY="216.0" prefHeight="40.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0">
<buttons>
<Button mnemonicParsing="false" onAction="#saveTabs" text="Save" />
<Button mnemonicParsing="false" onAction="#openTabs" text="Open" />
</buttons>
</ButtonBar>
</children>
</AnchorPane>
Main Class:
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 primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
Parent node = loader.load(Main.class.getClassLoader().getResource("fxml/TestFXML.fxml").openStream());
Scene scene = new Scene(node,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Controller:
package application;
import java.util.ArrayList;
import java.util.Collection;
import java.util.stream.Collectors;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
public class TestController {
#FXML
private TabPane tabPane;
#FXML
private Tab tab1, tab2, tab3, tab4;
Collection<Tab> tabs = new ArrayList<>();
Collection<String> openTabIds = new ArrayList<>();
#FXML
private void initialize() {
tabs.add(tab1);
tabs.add(tab2);
tabs.add(tab3);
tabs.add(tab4);
}
#FXML
void openTabs() {
openTabIds.stream().forEach(string -> {
tabs.stream()
.filter(tab -> tab.getId().equals(string)).findFirst()
.ifPresent(tab -> tabPane.getTabs().add(tab));
});
}
#FXML
void saveTabs() {
openTabIds = tabPane.getTabs().stream().map(tab -> tab.getId()).collect(Collectors.toList());
}
}
I am trying to create tabs dinamically. I would like that textFields, labels, buttons, etc keep the position in the tab. The problem is that the tab appears but content is empty. I am using fxml and, reading other post, I tried to create another FXML for new tabs but I don't know how.
rellenarCamposMascota method is where i wold like to create tabs dinamically.
package mrpuppy.controller.cliente;
import java.io.IOException;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import mrpuppy.DTO.ApplicationContextDTO;
import mrpuppy.entity.Cliente;
import mrpuppy.entity.Mascota;
import mrpuppy.service.ClienteService;
#Controller
public class EditarClienteControllerImpl implements EditarClienteController
{
private Stage primaryStage;
private Scene scene;
private FXMLLoader loader;
private final String css = this.getClass().getResource("/css/editarCliente.css").toExternalForm();
#Autowired
private ClienteService clienteService;
#Autowired
private ListaClientesController listaClientesController;
private int intTabs=0;
private Tab[] openTabs;
#FXML
private TabPane tabPane;
#FXML
private Tab tabMascota;
#FXML
private TextField fieldNombreCliente;
#FXML
private TextField fieldApellidos;
#FXML
private TextField fieldDni;
#FXML
private TextField fieldTelMovil;
#FXML
private TextField fieldTelFijo;
#FXML
private TextField fieldDireccion;
#FXML
private TextField fieldCorreo;
#FXML
private ComboBox<String> comboMascota;
#FXML
private ComboBox<String> comboTamano;
#FXML
private TextField fieldNombreMascota;
#FXML
private RadioButton radioAlergiaSi;
#FXML
private RadioButton radioAlergiaNo;
#FXML
private TextField fieldRaza;
#FXML
private TextField fieldPeso;
#FXML
private ComboBox<String> comboSexo;
#FXML
private ComboBox<String> comboAgresividad;
#FXML
private TextArea areaObservaciones;
#FXML
private Button buttonCancelarEditarCliente;
#FXML
private Button buttonAceptarEditarCliente;
private ApplicationContextDTO applicationContextDTO;
#Override
public void openWindow(Cliente cliente)
{
try
{
primaryStage = new Stage();
primaryStage.setResizable(false);
loader = new FXMLLoader(getClass().getResource("/view/editarCliente.fxml"));
loader.setController(this); //Establecemos esta clase como "controller"
scene = loader.load();
scene.getStylesheets().add(css);
primaryStage.setScene(scene);
primaryStage.initModality(Modality.APPLICATION_MODAL);
primaryStage.show();
rellenarCamposCliente(cliente);
rellenarCamposMascota(cliente);
buttonCancelarEditarCliente.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
primaryStage.close();
}
});
buttonAceptarEditarCliente.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
cliente.setNombre(fieldNombreCliente.getText());
cliente.setApellidos(fieldApellidos.getText());
cliente.setDni(fieldDni.getText());
cliente.setTelefonoMovil(Integer.parseInt(fieldTelMovil.getText()));
cliente.setTelefonoFijo(Integer.parseInt(fieldTelFijo.getText()));
cliente.setDireccion(fieldDireccion.getText());
cliente.setCorreo(fieldCorreo.getText());
clienteService.actualizarCliente(cliente);
primaryStage.close();
}
});
}
catch(IOException ioe)
{
System.out.println(ioe.getMessage());
}
}
private void rellenarCamposCliente(Cliente cliente)
{
applicationContextDTO = new ApplicationContextDTO();
applicationContextDTO.setClienteService();
clienteService = applicationContextDTO.getClienteService();
fieldNombreCliente.setText(cliente.getNombre());
fieldApellidos.setText(cliente.getApellidos());
fieldDni.setText(cliente.getDni());
fieldTelMovil.setText(String.valueOf(cliente.getTelefonoMovil()));
fieldTelFijo.setText(String.valueOf(cliente.getTelefonoFijo()));
fieldDireccion.setText(cliente.getDireccion());
fieldCorreo.setText(cliente.getCorreo());
return;
}
private void rellenarCamposMascota(Cliente cliente)
{
try
{
Collection<Mascota> mascotas = cliente.getMascotas();
for(Mascota mascota : mascotas)
{
Tab newTab = new Tab();
loader = new FXMLLoader(getClass().getResource("/view/mascotaTab.fxml"));
newTab.setContent(loader.load());
tabPane.getTabs().add(new Tab());
fieldNombreMascota.setText(mascota.getNombre());
fieldRaza.setText(mascota.getRaza());
comboSexo.setValue(mascota.getSexo());
fieldPeso.setText(String.valueOf(mascota.getPeso()));
comboTamano.setValue(mascota.getTamano());
comboAgresividad.setValue(mascota.getAgresividad());
areaObservaciones.setText(mascota.getObservaciones());
}
}
catch(IOException ioe)
{
System.out.println(ioe.getMessage());
}
}
}
Cliente tab must be static.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.collections.FXCollections?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.Scene?>
<Scene width="550" height="350" xmlns:fx="http://javafx.com/fxml">
<BorderPane id="root">
<top>
<TabPane fx:id="tabPane">
<tabs>
<Tab fx:id="tabCliente" text="Cliente" >
<content>
<AnchorPane fx:id="paneCliente">
<VBox fx:id="vBoxBloqueCliente">
<children>
<HBox fx:id="hBoxNombreApellidos">
<children>
<Label fx:id="labelNombre" text="Nombre:"/>
<TextField fx:id="fieldNombreCliente"/>
<Label fx:id="labelApellidos" text="Apellidos:"/>
<TextField fx:id="fieldApellidos"/>
</children>
</HBox>
<HBox fx:id="hBoxDniMovil">
<children>
<Label fx:id="labelDni" text="DNI:"/>
<TextField fx:id="fieldDni"/>
<Label fx:id="labelTelMovil" text="Teléfono Móvil:"/>
<TextField fx:id="fieldTelMovil"/>
</children>
</HBox>
<HBox fx:id="hBoxFijoDireccion">
<children>
<Label fx:id="labelTelFijo" text="Teléfono Fijo:
(opcional)"/>
<TextField fx:id="fieldTelFijo"/>
<Label fx:id="labelDireccion" text="Dirección:"/>
<TextField fx:id="fieldDireccion"/>
</children>
</HBox>
<HBox fx:id="hBoxCorreo">
<children>
<Label fx:id="labelCorreo" text="Correo:"/>
<TextField fx:id="fieldCorreo"/>
</children>
</HBox>
<HBox fx:id="hBoxBotonesCliente">
<children>
<Button fx:id="buttonCancelarEditarCliente" text="CANCELAR"/>
<Button fx:id="buttonAceptarEditarCliente" text="CONFIRMAR"/>
</children>
</HBox>
</children>
</VBox>
</AnchorPane>
</content>
</Tab>
<Tab fx:id="tabMascota" text="Mascota X" >
<content>
<AnchorPane fx:id="paneEditarMascota">
<VBox fx:id="vBoxBloqueEditarMascota">
<children>
<HBox fx:id="hBoxMascotaTamano">
<children>
<ComboBox fx:id="comboMascota">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Perro" />
<String fx:value="Gato" />
</FXCollections>
</items>
<value>
<String fx:value="Seleccionar mascota" />
</value>
</ComboBox>
<ComboBox fx:id="comboTamano">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Pequeño" />
<String fx:value="Mediano" />
<String fx:value="Grande" />
</FXCollections>
</items>
<value>
<String fx:value="Seleccionar tamaño" />
</value>
</ComboBox>
</children>
</HBox>
<HBox fx:id="hBoxNombreAlergia">
<fx:define>
<ToggleGroup fx:id="groupAlergia"/>
</fx:define>
<children>
<Label fx:id="labelNombreMascota" text="Nombre:"/>
<TextField fx:id="fieldNombreMascota"/>
<Label fx:id="labelAlergico" text="Alergico:"/>
<RadioButton fx:id="radioAlergiaSi" text="Si" toggleGroup="$groupAlergia"/>
<RadioButton fx:id="radioAlergiaNo" text="No" toggleGroup="$groupAlergia"/>
</children>
</HBox>
<HBox fx:id="hBoxRaza">
<children>
<Label fx:id="labelRaza" text="Raza:"/>
<TextField fx:id="fieldRaza"/>
<Label fx:id="labelPeso" text="Peso:"/>
<TextField fx:id="fieldPeso"/>
</children>
</HBox>
<HBox fx:id="hBoxSexoAgresividad">
<children>
<ComboBox fx:id="comboSexo">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Macho" />
<String fx:value="Hembra" />
</FXCollections>
</items>
<value>
<String fx:value="Seleccionar sexo" />
</value>
</ComboBox>
<ComboBox fx:id="comboAgresividad">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Tranquilo" />
<String fx:value="Nervioso" />
<String fx:value="Agresivo" />
</FXCollections>
</items>
<value>
<String fx:value="Seleccionar agresividad" />
</value>
</ComboBox>
</children>
</HBox>
<HBox fx:id="hBoxObservaciones">
<TextArea fx:id="areaObservaciones"/>
</HBox>
<HBox fx:id="hBoxBotonesAnadirMascota">
<Button fx:id="buttonVolverAnadirMascota"/>
<Button fx:id="buttonHomeAnadirMascota"/>
<Button fx:id="buttonAnadirMascota"/>
</HBox>
</children>
</VBox>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</top>
</BorderPane>
</Scene>
This is tabs fxml file code, label returns error. I don't know why.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.collections.FXCollections?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.Scene?>
<BorderPane>
<Label fx:id="labelRaza" text="Raza:"/>
</BorderPane>