GridPane not visible unless i resize window javaFx - java

when i start the application, TitledPane does not show the GridPane I have added. Surprisingly it's visible the moment i increase/decrease the window width. where am i missing?
Here is the Complete Code:
package com.ct.bic.comparator;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class Comparator extends Application {
#Override
public void start(Stage stage) {
GridPane dbGrid = new GridPane();
dbGrid.setId("dbGrid");
dbGrid.setAlignment(Pos.TOP_LEFT);
dbGrid.setHgap(10);
dbGrid.setVgap(10);
dbGrid.setPadding(new Insets(25, 25, 25, 25));
Label dbConnection = new Label("Database Configuration");
dbConnection.setId("dbConnection");
dbConnection.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
dbGrid.add(dbConnection, 0, 0, 2, 1);
Label server = new Label("Server");
server.setId("server");
dbGrid.add(server, 0, 1);
TextField serverText = new TextField();
serverText.setId("serverText");
dbGrid.add(serverText, 1, 1);
Label database = new Label("Database");
database.setId("database");
dbGrid.add(database, 0, 2);
TextField databaseText = new TextField();
databaseText.setId("databaseText");
dbGrid.add(databaseText, 1, 2);
Label user = new Label("User");
user.setId("user");
dbGrid.add(user, 0, 3);
TextField userText = new TextField();
userText.setId("userText");
dbGrid.add(userText, 1, 3);
Label password = new Label("Password");
password.setId("password");
dbGrid.add(password, 0, 4);
PasswordField passwordText = new PasswordField();
passwordText.setId("passwordText");
dbGrid.add(passwordText, 1, 4);
dbGrid.setId("passwordText");
/*GridPane dbGrid = DatabaseInputGrid.getDatabaseGrid();*/
TitledPane tp = new TitledPane("Database Configuration", dbGrid);
Scene scene = new Scene(tp, 500,500);
stage.setScene(scene);
stage.setTitle("Bic-Java Output Comparator Pro");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

I don't know the exact reason why, but it seems TitledPane is not resized if used as root for the Scene.
I tried something like this:
VBox vbox = new VBox();
vbox.getChildren().add(tp);
Scene scene = new Scene(vbox, 500,500);
Then everything works as expected.
Edit:
I have found this here:
Do not explicitly set the minimal, maximum, or preferred height of a
titled pane, as this may lead to unexpected behavior when the titled
pane is opened or closed.
So my guess is, when you set your TitledPane as root for the scene, it will try to set the preferred height, that leads to the mentioned "unexpected behaviour".

Related

Achieve Unique Column Width for each Cell in Different Rows with a GridPane?

I am trying to model credit card data in JavaFx using a GridPane:
My model contains 3 rows (Note: each field is comprised of label + text field):
Row 1: First name and last name (4 fields)
Row 2: Credit card number (2 fields)
Row 3: Expiration date - month, year + CVV (6 fields)
See screenshot below:
I was reading this tutorial which states:
All cells in the same row will have the same height, and all cells in
the same column will have the same width. Different rows can have
different heights and different columns can have different widths.
Are there any workarounds to to have different size columns on a row by row basis in a GridPane?
For the specific layout in the image, I would use a VBox with HBox for rows:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
public class App extends Application {
#Override
public void start(Stage stage) {
Label lblFirst = new Label("First");
Label lblLast = new Label("Last");
Label lblNumber = new Label("Card Number");
Label lblMonth = new Label("Month");
Label lblYear = new Label("Year");
Label lblCVV = new Label("CVV");
TextField txtFirst = new TextField();
TextField txtLast = new TextField();
TextField txtNumber = new TextField();
TextField txtMonth = new TextField();
TextField txtYear = new TextField();
TextField txtCVV = new TextField();
HBox row1 = new HBox(10);
HBox row2 = new HBox(10);
HBox row3 = new HBox(10);
row1.getChildren().add(createCell(lblFirst, txtFirst));
row1.getChildren().add(createCell(lblLast, txtLast));
row2.getChildren().add(createCell(lblNumber, txtNumber));
row3.getChildren().add(createCell(lblMonth, txtMonth));
row3.getChildren().add(createCell(lblYear, txtYear));
row3.getChildren().add(createCell(lblCVV, txtCVV));
VBox rows = new VBox(10, row1, row2, row3);
StackPane.setMargin(rows, new Insets(10));
StackPane root = new StackPane(rows);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private static HBox createCell(Label label, TextField text) {
HBox pane = new HBox(5, label, text);
label.setMinWidth(Pane.USE_PREF_SIZE);
text.setMinWidth(50);
pane.setAlignment(Pos.CENTER);
HBox.setHgrow(pane, Priority.ALWAYS);
HBox.setHgrow(text, Priority.ALWAYS);
return pane;
}
public static void main(String[] args) {
launch();
}
}
Output:
+1 for what #JamesD suggested and #Oboe answer. Ideally I would separate each row layout, to handle it in easy way than making it complex using only one GridPane.
Having said that, if you want to go with or learn about how you can do the similar layouting using one GridPane, the below implemenation may give you a quick idea.
Firstly split your layout into the required columns, to figure out how many total columns you need. (as in the below image)
Now you will know which node will sit in which column and how many columns it will occupy (colspan)
I will explain for one node:
Lets say you want insert the field of first name. If you notice in the picture, it is in rowIndex: 0, columnIndex: 1 and it is occupying 4 columns, so the colSpan value will be 4. Here we are not combining any rows, so the rowSpan value will be always 1.
pane.add(getField(), 1, 0, 4, 1); // node, colIndex, rowIndex, colSpan, rowSpan
Similarly you can relate the rest of the nodes layouting. And also for more precising you can set the prefered width of each column using ColumnConstraints. Below is the complete code for the layout & constraints:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CreditCardPaneDemo extends Application {
#Override
public void start(Stage stage) throws Exception {
VBox root = new VBox();
root.setPadding(new Insets(5));
root.setSpacing(10);
Scene scene = new Scene(root,300,200);
stage.setScene(scene);
stage.setTitle("CreditCard");
stage.show();
GridPane pane = new GridPane();
pane.setStyle("-fx-border-color:black;-fx-border-width:1px;-fx-background-color:yellow");
pane.setPadding(new Insets(5));
pane.setHgap(5);
pane.setVgap(5);
pane.add(getLabel("First"), 0, 0, 1, 1);
pane.add(getField(), 1, 0, 4, 1);
pane.add(getLabel("Last"), 5, 0, 1, 1);
pane.add(getField(), 6, 0, 2, 1);
pane.add(getLabel("Card Number"), 0, 1, 3, 1);
pane.add(getField(), 3, 1, 5, 1);
pane.add(getLabel("Month"), 0, 2, 2, 1);
pane.add(getField(), 2, 2, 2, 1);
pane.add(getLabel("Year"), 4, 2, 1, 1);
pane.add(getField(), 5, 2, 1, 1);
pane.add(getLabel("CVV"), 6, 2, 1, 1);
pane.add(getField(), 7, 2, 1, 1);
pane.getColumnConstraints().addAll(getCc(70), getCc(20), getCc(80), getCc(20), getCc(25), getCc(90), getCc(80), getCc(100));
CheckBox gridLines = new CheckBox("Show grid lines");
gridLines.selectedProperty().addListener((obs, old, val) -> pane.gridLinesVisibleProperty().set(val));
root.getChildren().addAll(gridLines, pane);
}
private ColumnConstraints getCc(double width) {
ColumnConstraints cc = new ColumnConstraints();
cc.setPrefWidth(width);
return cc;
}
private Label getLabel(String txt) {
Label lbl = new Label(txt);
lbl.setMinWidth(Region.USE_PREF_SIZE);
return lbl;
}
private TextField getField() {
TextField field = new TextField();
field.setMaxWidth(Double.MAX_VALUE);
return field;
}
}

How to align a ListView BASELINE in a GridPane

I'm currently writing a Java-FX program that contains a ListView in a GridPane. I want to align the listview by the baseline of its first item with the label to the left of the listview, but the listview is initially empty. It appears not aligned correctly, but jumps to the right position when it is populated and an item is selected.
I asume, in order to calculate the correct baseline offset, the listview needs to know its items before it is shown. So, how can I create an empty listview and fill it dynamically (by user actions), when it should be aligned BASELINE?
You can reproduce the effect with the following mcve (Java 8 u221):
import javafx.application.Application;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
public class ListViewAlignmentTest extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
#Override
public void start(Stage stage)
{
ListView<String> listview = new ListView<String>();
listview.setPrefSize(100.0, 100.0);
RowConstraints rc0 = new RowConstraints();
rc0.setValignment(VPos.BASELINE);
RowConstraints rc1 = new RowConstraints();
rc1.setValignment(VPos.BASELINE);
GridPane root = new GridPane();
root.getRowConstraints().add(0, rc0);
root.getRowConstraints().add(1, rc1);
root.setHgap(10);
root.setVgap(10);
root.add(new Label("Some text"), 0, 0);
root.add(new TextField(), 1, 0);
root.add(new Label("Other text"), 0, 1);
root.add(listview, 1, 1);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
listview.getItems().addAll("String1", "String2");
}
}
This is how the GUI looks initially: https://i.imgur.com/nUXqyDm.png
After selecting the first listview item it looks correct: https://i.imgur.com/i73kbKw.png
I expect the listview to be aligned BASELINE to the label next to it, but it first appears under the label.
Edit: updated complete code.
When replicated it so that it looks like as shown in image, https://i.imgur.com/i73kbKw.png
Code below makes it immovable.
import javafx.application.Application;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
public class ListViewAlignmentTest extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
#Override
public void start(Stage stage)
{
ListView<String> listview = new ListView<String>();
listview.setPrefSize(100.0, 100.0);
RowConstraints rc0 = new RowConstraints();
rc0.setFillHeight(true);
RowConstraints rc1 = new RowConstraints();
rc1.setFillHeight(true);
GridPane root = new GridPane();
root.getRowConstraints().add(0, rc0);
root.getRowConstraints().add(1, rc1);
root.setHgap(10);
root.setVgap(10);
root.add(new Label("Some text"), 0, 0);
root.add(new TextField(), 1, 0);
root.add(new Label("Other text"), 0, 1);
root.add(listview, 1, 1);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
listview.getItems().addAll("String1", "String2");
}
}
As a result, it does not move now. That should help.

GridPane doesn't align in center

I am making a Login Screen with a number pad, and I can't seem to center align a GridPane of buttons in a Pane. What am I doing wrong?
Main.java
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.input.KeyCombination;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) throws Exception{
Rectangle2D bounds = Screen.getPrimary().getBounds();
LoginScreen loginScreen = new LoginScreen(bounds.getWidth(), bounds.getHeight());
Scene scene = new Scene(loginScreen.get());
primaryStage.setScene(scene);
primaryStage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
primaryStage.show();
primaryStage.setFullScreen(true);
}
}
LoginScreen.java
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
public class LoginScreen {
private Pane root;
private GridPane numberPad;
public LoginScreen(double screenWidth, double screenHeight){
root = new Pane();
root.setPrefSize(screenWidth, screenHeight);
root.setBackground(new Background(new BackgroundFill(Color.AQUA, CornerRadii.EMPTY, Insets.EMPTY)));
numberPad = new GridPane();
Button button01 = new Button("1");
Button button02 = new Button("2");
Button button03 = new Button("3");
Button button04 = new Button("4");
Button button05 = new Button("5");
Button button06 = new Button("6");
Button button07 = new Button("7");
Button button08 = new Button("8");
Button button09 = new Button("9");
numberPad.setAlignment(Pos.CENTER);
numberPad.add(button01, 0, 0);
numberPad.add(button02, 1, 0);
numberPad.add(button03, 2, 0);
numberPad.add(button04, 0, 1);
numberPad.add(button05, 1, 1);
numberPad.add(button06, 2, 1);
numberPad.add(button07, 0, 2);
numberPad.add(button08, 1, 2);
numberPad.add(button09, 2, 2);
root.getChildren().addAll(numberPad);
}
public Pane get(){
return root;
}
}
GUI code is verbose, and this post editor isn't letting me post my question as is, so I need these extra lines to get it to accept my question. If I thought I could cut down my code to just the numberPad.setAlignment(Pos.Center) and still make it clear how I am attempting to center my GridPane I most certainly would. I do humbly thank those who might lend me their time to help me solve this issue I have.
Edit 01:
My issue is that the GridPane itself is drawn in the top left corner of the screen rather than in the center of the screen.
You need to actually set the alignment for the parent container. A Pane is not a valid container for doing this, however.
If you were to use a VBox instead, you could simply set its alignment as so:
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
That will cause all of the children of the VBox to be placed in the center.
The Pos enum also provides other methods of positioning, including TOP_CENTER, TOP_LEFT, and BOTTOM_RIGHT, for example.

JFXTabePane closing option is not working

I am trying to add close option in tabpane like a browser have it. Could you please tell me how to add closing feature in this tabpane? I tried this line but didn't solve my problem tabPane.setTabClosingPolicy(TabClosingPolicy.ALL_TABS);
I am using javafx jfoenix library for UI.
package tabsDemo;
import java.awt.Color;
import java.awt.Dimension;
import java.math.BigInteger;
import java.security.SecureRandom;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTabPane;
import com.jfoenix.controls.JFXTextField;
public class TabsDemo extends Application {
private String msg = "Tab 0";
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Tabs");
Group root = new Group();
Scene scene = new Scene(root, 800, 600);
JFXButton b1 = new JFXButton();
b1.setId("back");
b1.setGraphic(new ImageView(new Image("/tabsDemo/back.png")));
b1.setMinWidth(20);
b1.setMinHeight(20);
b1.setMaxWidth(20);
b1.setMaxHeight(20);
JFXButton b2 = new JFXButton();
b2.setId("farword");
b2.setGraphic(new ImageView(new Image("/tabsDemo/forward.png")));
b2.setMinWidth(20);
b2.setMinHeight(20);
b2.setMaxWidth(20);
b2.setMaxHeight(20);
JFXButton b3 = new JFXButton();
b3.setId("refresh");
b3.setGraphic(new ImageView(new Image("/tabsDemo/refresh.png")));
b3.setMinWidth(20);
b3.setMinHeight(20);
b3.setMaxWidth(20);
b3.setMaxHeight(20);
JFXTextField t1 = new JFXTextField();
t1.setMinWidth(100);
// t1.setPrefWidth(900);
// t1.setMaxWidth(1000);
t1.setMinHeight(30);
t1.setMaxHeight(30);
GridPane gridPane = new GridPane();
gridPane.setHgap(4);
gridPane.add(b1, 0, 0);
gridPane.add(b2, 1, 0);
gridPane.add(b3, 2, 0);
gridPane.add(t1, 3, 0);
gridPane.setHgrow(t1, Priority.ALWAYS);
BorderPane borderPane = new BorderPane();
borderPane.setTop(gridPane);
JFXTabPane tabPane = new JFXTabPane();
Tab tab1 = new Tab();
tab1.setText("Tab1");
tab1.setContent(borderPane);
VBox vbox = new VBox();
vbox.getChildren().addAll(new JFXButton("B1"), new JFXButton("B2"), new JFXButton("B3"), new JFXButton("B4"));
Tab tab2 = new Tab();
tab2.setText("Tab2");
tab2.setContent(vbox);
tabPane.getTabs().addAll(tab1, tab2);
tabPane.setPrefSize(800, 600);
// I add here the closing option for tab but it's not working
tabPane.setTabClosingPolicy(TabClosingPolicy.ALL_TABS);
SingleSelectionModel<Tab> selectionModel = tabPane.getSelectionModel();
selectionModel.select(1);
JFXButton button = new JFXButton("Add New Tab");
button.setOnMouseClicked((o) -> {
Tab temp = new Tab();
int count = tabPane.getTabs().size();
temp.setText(msg + count);
temp.setContent(new Label("Tab 0" + count));
tabPane.getTabs().add(temp);
});
borderPane.setRight(button);
tabPane.setMaxSize(800, 600);
/*
* HBox hbox = new HBox(); hbox.getChildren().addAll(button, tabPane);
* hbox.setSpacing(50); hbox.setAlignment(Pos.CENTER);
* hbox.setStyle("-fx-padding:20");
*/
BorderPane rootBorderpane = new BorderPane();
rootBorderpane.setCenter(tabPane);
root.getChildren().addAll(rootBorderpane);
scene.getStylesheets().add(TabsDemo.class.getResource("jfoenix-components.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setTitle("JFX Tabs Demo");
}
private SecureRandom random = new SecureRandom();
public String nextSessionId() {
return new BigInteger(50, random).toString(16);
}
}
Thank you!
Your JFXTabPane is a custom component from the JFoenix library, so there's no guarantee that all standard JavaFX settings, such as TabClosingPolicy in your case, are fully implemented.
I checked their GitHub repository and looks like there's an unresolved issue regarding this missing feature. Someone forked the repository, apparently resolved the problem and submitted a pull request, but it's still has an open status. In other words, the changes are not included in the current build, so the bug still exists.
My suggestion is to stick with the standard JavaFX components, which should provide everything you need to create simple applications, including the closeable tabs, which are are working well as presented in the following example.
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("JFX Tabs Demo");
TabPane tabPane = new TabPane();
tabPane.setTabClosingPolicy(TabClosingPolicy.ALL_TABS);
tabPane.getTabs().add(new Tab("Test"));
Scene scene = new Scene(tabPane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}

Why am I getting InvocationTargetException when trying to use css with javafx?

I am new to javafx and am trying to connect my class to my CSS file however when I use:
scene.getStylesheets().add("Viper.css");
I get the following warning:
Dec 08, 2016 9:12:54 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "Viper.css" not found.
But when I use:
scene.getStylesheets().add(getClass().getResource("/resources/CSS/Viper.css").toExternalForm());
I get an InvocationTargetException
Here is my entire class and I am positive that the filepath is correct. I am using NetBeans IDE.
package com.GUI;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class window extends Application{
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("OmegaBrain");
//Create Panes
Pane titlePane = new Pane();
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text sceneTitle = new Text("Welcome To OmegaBrain");
sceneTitle.setFont(Font.font("Helvetica", FontWeight.NORMAL, 20));
grid.add(sceneTitle, 0, 0, 4, 1);
Scene scene = new Scene(grid, 300, 275);
scene.getStylesheets().add("/resources/CSS/Viper.css");
primaryStage.setScene(scene);
primaryStage.show();
Button play = new Button("Play");
grid.add(play, 1, 1);
Button leaderboard = new Button("Leaderboard");
grid.add(leaderboard, 2, 1);
Button faq = new Button("FAQs");
grid.add(faq, 3, 1);
Button exit = new Button("Exit");
grid.add(exit, 4, 1);
play.setOnAction((ActionEvent e) -> {
System.out.println("The play button was clicked!");
});
}
public static void main(String[]args){
launch(args);
}
}
Assuming that your application is built with this hierarchy :
Application
->src
-->com/GUI/window.java
-->resources/CSS/Viper.css
Then this piece of code should work :
scene.getStylesheets().add(getClass().getResource("/resources/CSS/Viper.css").toExternalForm());
// or
scene.getStylesheets().add("/resources/CSS/Viper.css");
You can solve it with scene.getStylesheets().add("Package Name/Viper.css"));

Categories