I am new to JavaFx:
In my FXML I defined a linechart and over a controller I want to change e.g. the title of the chart.
But somehow it is not working.
Here the FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.ui.views.view2.viewView2Controller">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Label text="View 2 Area" />
<Button mnemonicParsing="false" onAction="#nextPane" text="view 1 page" />
<LineChart fx:id="testChart">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
</children>
</VBox>
</children>
</StackPane>
Here the controller Code:
package com.ui.views.view2;
import com.ui.libs.VistaNavigator;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.chart.*;
public class viewView2Controller {
#FXML
private LineChart<String,Number> testChart;
#FXML
private Axis<String> xAxis;
#FXML
private Axis<Number> yAxis;
public viewView2Controller()
{
xAxis = new CategoryAxis(); // we are gonna plot against time
yAxis = new NumberAxis();
xAxis.setLabel("Time/s");
xAxis.setAnimated(false); // axis animations are removed
yAxis.setLabel("Value");
yAxis.setAnimated(false); // axis animations are removed
//creating the line chart with two axis created above
testChart = new LineChart<>(xAxis,yAxis);
testChart.setTitle("my first JavaFX Chart");
testChart.setAnimated(false);
}
public void nextPane(ActionEvent actionEvent) {
VistaNavigator.loadVista(VistaNavigator.viewConfig);
}
}
Whats wrong in my code and what do I need to change that I am able to change the chart title and afterwards with the new recommendation also able to populate values into it. :-)
BR
Dieter
Related
I want my Chat Window to be reziable and scrollable, so far everything works except the ChatLog itself.
I need a scroll bar, that's why I put the VBox inside of a ScrollPane (which is child of an AnchorPane), but this way only the ScrollPane is responsive (thanks to Anchor Values). If I unwrap VBox I can set Anchor Values, then it works but I'm loosing my scroll bar.
How can I mantain the scroll bar for ChatLog AND make it responsive (attached on the right side)?
FXML:
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-background-color: #5b2529;" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.lmu.jungejunkervp.ClientWindowController">
<children>
<ScrollPane fx:id="scrollPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="265.0" prefWidth="592.0" AnchorPane.bottomAnchor="57.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<content>
<VBox fx:id="chatLog" prefHeight="265.0" prefWidth="575.0" />
</content></ScrollPane>
<TextArea fx:id="messageBox" layoutX="5.0" layoutY="349.0" onKeyPressed="#onEnterSend" prefHeight="47.0" prefWidth="536.0" promptText="enter message..." AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="61.0" />
<Button fx:id="sendButton" mnemonicParsing="false" onAction="#setSendButtonAction" onMouseClicked="#setSendButtonAction" prefHeight="47.0" prefWidth="52.0" text="Send" AnchorPane.bottomAnchor="5.0" AnchorPane.rightAnchor="5.0" />
</children>
</AnchorPane>
public void addLabel(String message, Pos position) {
HBox hBox = new HBox();
hBox.setAlignment(position);
hBox.setPadding(new Insets(5, 5, 5, 10));
Text text = new Text(message);
TextFlow textFlow = new TextFlow(text);
textFlow.setStyle("-fx-background-color: rgb(233,233,235);" +
"-fx-background-radius: 20px");
textFlow.setPadding(new Insets(5, 10, 5, 10));
hBox.getChildren().add(textFlow);
Platform.runLater(new Runnable() {
#Override
public void run() {
chatLog.getChildren().add(hBox);
}
});
}
public void setSendButtonAction() {
String message = messageBox.getText().replaceAll("[\n\r]", "");
try {
if (!message.isEmpty()) {
// show message on the sending client window
addLabel(message, Pos.CENTER_RIGHT);
}
}
To answer your actual question, below is what you need add to the ScrollPane (in fxml with your current layout).
fitToHeight="true" fitToWidth="true"
The above code will make your VBox responsive with the ScrollPane.
I also suggest to change your layout to get rid of AnchorPane (will all those hardcoded positions). You can use VBox/HBox in conjuction with vgrow/hgrow policies. The optimized fxml will be as below:
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
<?import javafx.geometry.Insets?>
<VBox style="-fx-background-color: #5b2529;" spacing="5" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.lmu.jungejunkervp.ClientWindowController">
<children>
<ScrollPane fx:id="scrollPane" prefHeight="265.0" prefWidth="592.0" fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS">
<content>
<VBox fx:id="chatLog"/>
</content>
</ScrollPane>
<HBox spacing="5">
<TextArea fx:id="messageBox" onKeyPressed="#onEnterSend" prefHeight="47.0" promptText="enter message..." HBox.hgrow="ALWAYS" />
<Button fx:id="sendButton" mnemonicParsing="false" onAction="#setSendButtonAction" prefHeight="47.0" minWidth="52.0" text="Send"/>
</HBox>
</children>
<padding>
<Insets topRightBottomLeft="5"/>
</padding>
</VBox>
Having said that, I think you need to consider changing your layout to what #jewelsea mentioned in the provided example (using ListView).
To summarize, I have various FXML files and various corresponding controllers, and to switch between them I am using the following code:
#FXML
public void openInputPane() throws IOException {
BorderPane inputMenu = FXMLLoader.load(getClass().getResource("inputSection/firstPage/inputEquationMenu.fxml"));
mainBorderPane.getChildren().setAll(inputMenu);
}
My main fxml file is a GridPane and the rest are BorderPanes, and this method of using .getChildren().setAll(anotherPane) works perfectly until I try to return to the main GridPane:
public void goToMainMenu() throws IOException {
URL url = new File("C:\\Users\\Luisa" +
"\\IdeaProjects\\IA\\src\\sample\\mainmenu.fxml").toURI().toURL();
GridPane mainMenu = FXMLLoader.load(url);
successMessageBorderPane.getChildren().setAll(mainMenu);
}
The above code does display the original main menu, but messes up the formatting, attached are pictures of the main menu when I first open the programme and the main menu after returning to it.
after returning to main
main at the start of the programme
My question is, what is messing up the formatting when I go back to the main page, and what do I have to do to fix it?
For more details I'm attaching the fxml file for the main GridPane and the last BorderPane (the one where a button is clicked to return to the main GridPane) and their respective controllers.
mainmenu.fxml
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.text.Font?> <?import javafx.scene.layout.HBox?>
<GridPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml"
stylesheets="#resources/styles.css" fx:id="mainBorderPane" prefHeight="400" prefWidth="500" vgap="20"
hgap="20" alignment="CENTER">
<HBox GridPane.columnIndex="0" GridPane.rowIndex="0">
<Label text="Physics Formula Storage">
<font>
<Font size="40"/>
</font>
</Label>
</HBox>
<HBox GridPane.rowIndex="1" spacing="35">
<Button text="Insert Equations" onAction="#openInputPane"/>
<Button text="Use Equations"/>
</HBox>
<HBox GridPane.rowIndex="2" spacing="20"
prefWidth="340">
<Label text="Input new equations along with their properties into the storage system" prefWidth="150"
style= "-fx-font-size: 14"/>
<Label text="Find and use equations already in the storage system" prefWidth="150" style= "-fx-font-size: 14"/>
</HBox>
</GridPane>
Controller
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import java.io.IOException;
public class Controller {
#FXML
GridPane mainBorderPane;
// switching to the input pane if the button is clicked
#FXML
public void openInputPane() throws IOException {
BorderPane inputMenu = FXMLLoader.load(getClass().getResource("inputSection/firstPage/inputEquationMenu.fxml"));
mainBorderPane.getChildren().setAll(inputMenu);
}
}
successMessageMenu.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Line?>
<?import javafx.scene.text.Font?>
<BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.inputSection.thirdPage.SuccessMessageController"
prefHeight="400.0" prefWidth="600.0" stylesheets="#../../resources/styles.css"
fx:id="successMessageBorderPane">
<padding>
<Insets top="30" right="50" bottom="30" left="50"/>
</padding>
<top>
<VBox prefHeight="50">
<Label alignment="BOTTOM_LEFT" text="Equation added successfully">
<font>
<Font size="17"/>
</font>
</Label>
<Line startX="50" startY="50" endX="550" endY="50"/>
</VBox>
</top>
<center>
<VBox prefHeight="300" alignment="CENTER">
<Label text="Equation has been added successfully" style="-fx-font-style: italic">
<font>
<Font size="40"/>
</font>
</Label>
</VBox>
</center>
<bottom>
<VBox alignment="BOTTOM_CENTER" prefHeight="50">
<Button text="Return to main menu" fx:id="mainMenuButton"
onAction="#goToMainMenu"/>
</VBox>
</bottom>
</BorderPane>
successMenuController
public class SuccessMessageController {
#FXML
Button mainMenuButton;
#FXML
BorderPane successMessageBorderPane;
public void goToMainMenu() throws IOException {
URL url = new File("C:\\Users\\Luisa" +
"\\IdeaProjects\\IA\\src\\sample\\mainmenu.fxml").toURI().toURL();
GridPane mainMenu = FXMLLoader.load(url);
successMessageBorderPane.getChildren().setAll(mainMenu);
}
}
(it is my first time asking a question, do tell me if I need to add anymore code, thank you!)
I fail to center a Button in a VBox in Java code!
I used Scene Builder to create a SplitPane with the left AnchorPane having a Button centered in a VBox.
I want to recreate this, a Button in a VBox, in the right AnchorPane but not in FXML, in Java Code. But the right Button does not center, although I use vb.setAlignment(Pos.CENTER); :
My FXML code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="testimageview.MainViewController">
<children>
<SplitPane dividerPositions="0.5" prefHeight="200.0" prefWidth="400.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane fx:id="leftAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<VBox alignment="CENTER" prefHeight="198.0" prefWidth="171.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Button mnemonicParsing="false" text="FXML" />
</children>
</VBox>
</children>
</AnchorPane>
<AnchorPane fx:id="rightAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
</items>
</SplitPane>
</children>
</AnchorPane>
And my Java Controller class code:
package testimageview;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
public class MainViewController implements Initializable {
#FXML
private AnchorPane leftAnchorPane;
#FXML
private AnchorPane rightAnchorPane;
public MainViewController() {
}
#Override
public void initialize(URL url, ResourceBundle rb) {
VBox.setVgrow(leftAnchorPane, Priority.ALWAYS);
VBox vb = new VBox();
Button rightButton = new Button();
rightButton.setText("Java");
vb.setAlignment(Pos.CENTER);
vb.getChildren().addAll(rightButton);
rightAnchorPane.getChildren().add(vb);
}
}
Well you did not define the dimensions for the VBox so by default (inside a ScrollPane) it will fit the size of it's children in your case a Button size like 50,50 or something like that, so you can not see the alignment. All you need to do is to define the size of the VBox to match the size of the second AnchorPane or you can just bind their dimensions ( Width, height ) like :
vb.prefWidthProperty().bind(rightAnchorPane.widthProperty());
vb.prefHeightProperty().bind(rightAnchorPane.heightProperty());
I am trying to make a login page which is full screen,I followed another question in stackoverflow and made my login window it looks perfect with all controls, buttons etc aligned to center ,But as soon as I change the screen resolution every thing becomes unaligned . how can I solve this?.I am using scene builder
fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1360.0" spacing="20.0" styleClass="background" stylesheets="#../UICoreComponents/JMetroDarkTheme.css" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.MyCompany.attendanceMaster.LoginController">
<children>
<Pane prefHeight="200.0" prefWidth="278.0">
<children>
<TextField fx:id="userNameTF" layoutX="6.0" layoutY="55.0" prefHeight="25.0" prefWidth="248.0" promptText="Username" />
<Button layoutX="14.0" layoutY="141.0" mnemonicParsing="false" onAction="#loginBtnClicked" prefHeight="25.0" prefWidth="101.0" text="Login" />
<Button layoutX="145.0" layoutY="141.0" mnemonicParsing="false" onAction="#clearBtnClicked" prefHeight="25.0" prefWidth="101.0" text="Clear" />
<Label layoutX="99.0" layoutY="14.0" prefHeight="17.0" prefWidth="62.0" text="Login" textFill="WHITE">
<font>
<Font size="22.0" />
</font></Label>
<PasswordField fx:id="passwordTF" layoutX="6.0" layoutY="100.0" prefHeight="25.0" prefWidth="248.0" promptText="Password" />
</children>
</Pane>
</children>
<padding>
<Insets left="550.0" right="550.0" />
</padding>
</VBox>
Main.java
import com.MyCompany.Network.ClientMaster;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Screen;
import javafx.stage.Stage;
/**
*
* #author shersha
*/
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception {
new StaticController();
new ClientMaster();
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.setFullScreen(true);
stage.setResizable(false);
Parent root = StaticController.LOGIN_LOADER.getRoot();
Scene scene = new Scene(root);
scene.getStylesheets().add("com/MyCompany/UICoreComponents/JMetroDarkTheme.css");
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
My screen resolution is 1360X768 perfectly alligned
**Screen resolution at 1024X768 **
My final question is how can I make a javafx application that will run screen resolution Independent?(My window size is maximized and not resizable)
Thank you.
Your layout is based on a VBox and then you are using padding to align it. As these values will be the same for all window sizes, it will only work in one case.
Instead you should use a StackPane or which centers the content. Into that StackPane you add your Pane, without any padding. Eventually you need to bind the scene width and heigh to the values of the StackPane.
I would like to have buttons with equal(maximum) width in a gridpane.
When I'm trying to set it directly in FXML - it works perfectly.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="TestController">
<children>
<GridPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.bottomAnchor="0"
AnchorPane.topAnchor="0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" percentWidth="50.0"/>
<ColumnConstraints hgrow="SOMETIMES" percentWidth="50.0"/>
</columnConstraints>
<children>
<Button maxWidth="Infinity" text="Button1" GridPane.columnIndex="0"/>
<Button maxWidth="Infinity" text="Button2" GridPane.columnIndex="1"/>
</children>
</GridPane>
</children>
</AnchorPane>
But when I wanted to separate the whole grid into a custom control, the buttons stopped to fill the available width.
Here's a FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import CustomGridPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="TestController">
<children>
<CustomGridPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.bottomAnchor="0" AnchorPane.topAnchor="0">
</CustomGridPane>
</children>
</AnchorPane>
And an extension:
public class CustomGridPane extends GridPane {
private Button button1 = new Button("button1");
private Button button2 = new Button("button2");
public CustomGridPane() {
super();
button1.maxWidth(Double.MAX_VALUE);
button2.maxWidth(Double.MAX_VALUE);
getColumnConstraints().add(new ColumnConstraints());
getColumnConstraints().add(new ColumnConstraints());
getColumnConstraints().get(0).setPercentWidth(50);
getColumnConstraints().get(0).setHgrow(Priority.SOMETIMES);
getColumnConstraints().get(1).setPercentWidth(50);
getColumnConstraints().get(1).setHgrow(Priority.SOMETIMES);
add(button1, 0, 0);
add(button2, 1, 0);
}
}
Am I missing something?
You are using maxWidth property getter instead of the method setMaxWidth (setter).
Please see the documentation of Button here
public final double maxWidth(double height)
Called during layout to determine the maximum width for this node. Returns the value from computeMaxWidth(forHeight) unless the application overrode the maximum width by setting the maxWidth property.
Replace the two lines with maxWidth(...) by these ones:
button1.setMaxWidth(Double.MAX_VALUE);
button2.setMaxWidth(Double.MAX_VALUE);
This can be achieved inside scene builder also...
I required this, while creating a calculator, with the buttons inside gridpane.
Happy Coding (: