Why are the buttons and textfields and can not be clicked on? - javafx

`A JavaFX program with a GridPane and 'regular' Pane were used both inside a StackPane. The GridPane has text fields and a button however they are not able to be interacted with for some reason.
This is the code:
package application;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import java.util.Arrays;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.paint.Color;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Label Appearances = new Label("Champions League Appearances: ");
Label Goals = new Label("Champions League Goals: ");
Label Assists = new Label("Champions League Assists: ");
Label Ronaldo = new Label(" Ronaldo: ");
Label Messi = new Label(" Messi: ");
Label Lewandowski = new Label(" Lewandowski: ");
Label Benzema = new Label(" Benzema: ");
Label Raul = new Label(" Raúl: ");
Label van_Nistelrooy = new Label(" van Nistelrooy: ");
Label Muller = new Label(" Müller: ");
Label Henry = new Label(" Henry: ");
Label Ibrahimovic = new Label(" Ibrahimović: ");
Label Shevchenko = new Label(" Shevchenko: ");
TextField Txt1 = new TextField();
TextField Txt2 = new TextField();
TextField Txt3 = new TextField();
TextField Txt4 = new TextField();
TextField Txt5 = new TextField();
TextField Txt6 = new TextField();
TextField Txt7 = new TextField();
TextField Txt8 = new TextField();
TextField Txt9 = new TextField();
TextField Txt10 = new TextField();
TextField Txt11 = new TextField();
TextField Txt12 = new TextField();
TextField Txt13 = new TextField();
TextField Txt14 = new TextField();
TextField Txt15 = new TextField();
TextField Txt16 = new TextField();
TextField Txt17 = new TextField();
TextField Txt18 = new TextField();
TextField Txt19 = new TextField();
TextField Txt20 = new TextField();
TextField Txt21 = new TextField();
TextField Txt22 = new TextField();
TextField Txt23 = new TextField();
TextField Txt24 = new TextField();
TextField Txt25 = new TextField();
TextField Txt26 = new TextField();
TextField Txt27 = new TextField();
TextField Txt28 = new TextField();
TextField Txt29 = new TextField();
TextField Txt30 = new TextField();
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER_LEFT);
grid.setHgap(10);
grid.setVgap(10);
grid.add(Appearances, 1, 0);
grid.add(Goals, 2, 0);
grid.add(Assists, 3, 0);
grid.add(Ronaldo, 0, 1);
grid.add(Messi, 0, 2);
grid.add(Lewandowski, 0, 3);
grid.add(Benzema, 0, 4);
grid.add(Raul, 0, 5);
grid.add(van_Nistelrooy, 0, 6);
grid.add(Muller, 0, 7);
grid.add(Henry, 0, 8);
grid.add(Ibrahimovic, 0, 9);
grid.add(Shevchenko, 0, 10);
grid.add(Txt1, 1, 1);
Txt1.setAlignment(Pos.CENTER);
grid.add(Txt2, 2, 1);
Txt2.setAlignment(Pos.CENTER);
grid.add(Txt3, 3, 1);
Txt3.setAlignment(Pos.CENTER);
grid.add(Txt4, 1, 2);
Txt4.setAlignment(Pos.CENTER);
grid.add(Txt5, 2, 2);
Txt5.setAlignment(Pos.CENTER);
grid.add(Txt6, 3, 2);
Txt6.setAlignment(Pos.CENTER);
grid.add(Txt7, 1, 3);
Txt7.setAlignment(Pos.CENTER);
grid.add(Txt8, 2, 3);
Txt8.setAlignment(Pos.CENTER);
grid.add(Txt9, 3, 3);
Txt9.setAlignment(Pos.CENTER);
grid.add(Txt10, 1, 4);
Txt10.setAlignment(Pos.CENTER);
grid.add(Txt11, 2, 4);
Txt11.setAlignment(Pos.CENTER);
grid.add(Txt12, 3, 4);
Txt12.setAlignment(Pos.CENTER);
grid.add(Txt13, 1, 5);
Txt13.setAlignment(Pos.CENTER);
grid.add(Txt14, 2, 5);
Txt14.setAlignment(Pos.CENTER);
grid.add(Txt15, 3, 5);
Txt15.setAlignment(Pos.CENTER);
grid.add(Txt16, 1, 6);
Txt16.setAlignment(Pos.CENTER);
grid.add(Txt17, 2, 6);
Txt17.setAlignment(Pos.CENTER);
grid.add(Txt18, 3, 6);
Txt18.setAlignment(Pos.CENTER);
grid.add(Txt19, 1, 7);
Txt19.setAlignment(Pos.CENTER);
grid.add(Txt20, 2, 7);
Txt20.setAlignment(Pos.CENTER);
grid.add(Txt21, 3, 7);
Txt21.setAlignment(Pos.CENTER);
grid.add(Txt22, 1, 8);
Txt22.setAlignment(Pos.CENTER);
grid.add(Txt23, 2, 8);
Txt23.setAlignment(Pos.CENTER);
grid.add(Txt24, 3, 8);
Txt24.setAlignment(Pos.CENTER);
grid.add(Txt25, 1, 9);
Txt25.setAlignment(Pos.CENTER);
grid.add(Txt26, 2, 9);
Txt26.setAlignment(Pos.CENTER);
grid.add(Txt27, 3, 9);
Txt27.setAlignment(Pos.CENTER);
grid.add(Txt28, 1, 10);
Txt28.setAlignment(Pos.CENTER);
grid.add(Txt29, 2, 10);
Txt29.setAlignment(Pos.CENTER);
grid.add(Txt30, 3, 10);
Txt30.setAlignment(Pos.CENTER);
Pane BarGraph = new Pane();
ObservableList list = BarGraph.getChildren();
Line lin = new Line(630,450,1260,450);
Rectangle RonaldoApps = new Rectangle(630,400,50,50);
RonaldoApps.setFill(Color.DARKBLUE);
list.addAll(lin,RonaldoApps);
StackPane rootPane = new StackPane(grid, BarGraph);
Button SaveData = new Button("Save Changes");
SaveData.setOnAction(e ->{
double RonApps = Double.parseDouble(Txt1.getText().toString());
RonaldoApps.setHeight(RonApps);
});
grid.add(SaveData, 3, 11);
Scene scene = new Scene(rootPane, 1275, 570);
primaryStage.setTitle("CSC226 Project - All-Time UEFA Champions League Statistics");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {launch(args);}
}
I have tried to change the positioning of the grid and tried to change the types of panes but it did not work.`

Instead of using a Pane for BarGraph you could use a Group instead. Using a Pane does not make much sense here anyway and just triggers the problem you are seeing.

Related

Is it possible to add a LinearGradient fill to an SVGPath that already has an ImagePattern Fill?

In my main application I have some SVGPaths that I add to an XYChart. Sometimes they have an ImagePattern fill which now needs to have a LinearGradient fill. The ImagePattern fill is a crosshatch and this needs to be colored with the LinearGradient the same as if it was a solid Rectangle with a LinearGradient applied. The SVGPath also has a dotted outline and the LinearGradient should fill the dotted outline and the ImagePattern fill as it they were part of the same shape.
I've written some sample code to show where I'm at. This colors the crosshatch as it's created and looks ok but isn't the effect I describe above as each cross in the ImagePattern has the LinearGradient applied individually. Ideally the LinearGradient would just be applied to the final SVGPath once the ImagePattern fill has been applied.
I've also tried some effects using Blend and ColorInput but haven't managed to get any closer to the solution.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.ImagePattern;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Line;
import javafx.scene.shape.SVGPath;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
List<Color> colors = Arrays.asList(Color.RED, Color.YELLOW, Color.GREEN);
ArrayList<Stop> stops = new ArrayList<>(colors.size() * 2);
for (int i = 0; i < colors.size(); i++) {
stops.add(new Stop(getOffset(i, colors.size()), colors.get(i)));
stops.add(new Stop(getOffset(i + 1, colors.size()), colors.get(i)));
}
LinearGradient lg = new LinearGradient(0, 0, 20, 20, false, CycleMethod.REPEAT, stops);
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
Image hatch = createCrossHatch(lg);
ImagePattern pattern = new ImagePattern(hatch, 0, 0, 10, 10, false);
svgPath.setFill(pattern);
svgPath.setStroke(lg);
BorderPane root = new BorderPane();
root.setCenter(svgPath);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
catch (Exception e) {
e.printStackTrace();
}
}
protected static Image createCrossHatch(Paint paint) {
Pane pane = new Pane();
pane.setPrefSize(20, 20);
pane.setStyle("-fx-background-color: transparent;");
Line fw = new Line(-5, -5, 25, 25);
Line bw = new Line(-5, 25, 25, -5);
fw.setStroke(paint);
bw.setStroke(paint);
fw.setStrokeWidth(3);
bw.setStrokeWidth(3);
pane.getChildren().addAll(fw, bw);
new Scene(pane);
SnapshotParameters sp = new SnapshotParameters();
sp.setFill(Color.TRANSPARENT);
return pane.snapshot(sp, null);
}
private double getOffset(double i, int count) {
return (((double) 1) / (double) count * (double) i);
}
public static void main(String[] args) {
launch(args);
}
}
If you run the supplied code you will see it draws a dog bone. The lineargradient colors of the dashed outline should continue through the cross hatch ImagePattern fill. I'm aware of why the hatched ImagePattern is colored like it is but this is the best compromise I have at present. As mentioned I'd like to be able to applied the LinearGradient fill to the whole shape once the ImagePattern fill has been applied so the LinearGradient affects the whole shape the same.
Thanks
There is no direct way to apply and combine two paints over one single node. We can overlay many different paints (like solid, linear gradients or even image patterns) using background color via css, but that won't combine.
So in order to combine two different paints, on one side a linear gradient, on the other a pattern fill, we need to apply them to two nodes, and use a blending effect between both paints.
According to the code posted, this is the SVGPath with the linear gradient:
#Override
public void start(Stage primaryStage) {
Node base = getNodeWithGradient();
BorderPane root = new BorderPane();
Group group = new Group(base);
root.setCenter(group);
Scene scene = new Scene(root, 400, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private SVGPath getNodeWithGradient() {
List<Color> colors = Arrays.asList(Color.RED, Color.YELLOW, Color.GREEN);
ArrayList<Stop> stops = new ArrayList<>(colors.size() * 2);
for (int i = 0; i < colors.size(); i++) {
stops.add(new Stop(getOffset(i, colors.size()), colors.get(i)));
stops.add(new Stop(getOffset(i + 1, colors.size()), colors.get(i)));
}
LinearGradient lg = new LinearGradient(0, 0, 20, 20, false, CycleMethod.REPEAT, stops);
SVGPath svgPath = getSVGPath();
svgPath.setFill(lg);
svgPath.setStroke(lg);
return svgPath;
}
private SVGPath getSVGPath() {
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
return svgPath;
}
private double getOffset(double i, int count) {
return (((double) 1) / (double) count * (double) i);
}
While this is the SVGPath with the image pattern fill:
#Override
public void start(Stage primaryStage) {
Node overlay = getNodeWithPattern();
BorderPane root = new BorderPane();
Group group = new Group(overlay);
root.setCenter(group);
Scene scene = new Scene(root, 400, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private SVGPath getNodeWithPattern() {
Image hatch = createCrossHatch();
ImagePattern pattern = new ImagePattern(hatch, 0, 0, 10, 10, false);
SVGPath svgPath = getSVGPath();
svgPath.setFill(pattern);
return svgPath;
}
private SVGPath getSVGPath() {
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
return svgPath;
}
private static Image createCrossHatch() {
Pane pane = new Pane();
pane.setPrefSize(20, 20);
Line fw = new Line(-5, -5, 25, 25);
Line bw = new Line(-5, 25, 25, -5);
fw.setStroke(Color.BLACK);
bw.setStroke(Color.BLACK);
fw.setStrokeWidth(3);
bw.setStrokeWidth(3);
pane.getChildren().addAll(fw, bw);
new Scene(pane);
SnapshotParameters sp = new SnapshotParameters();
return pane.snapshot(sp, null);
}
Now the trick is to combine both SVGPath nodes, adding a blending mode to the one on top.
According to JavaDoc for BlendMode.ADD:
The color and alpha components from the top input are added to those from the bottom input.
#Override
public void start(Stage primaryStage) {
Node base = getNodeWithGradient();
Node overlay = getNodeWithPattern();
overlay.setBlendMode(BlendMode.ADD);
BorderPane root = new BorderPane();
Group group = new Group(base, overlay);
root.setCenter(group);
Scene scene = new Scene(root, 400, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private SVGPath getNodeWithGradient() {
List<Color> colors = Arrays.asList(Color.RED, Color.YELLOW, Color.GREEN);
ArrayList<Stop> stops = new ArrayList<>(colors.size() * 2);
for (int i = 0; i < colors.size(); i++) {
stops.add(new Stop(getOffset(i, colors.size()), colors.get(i)));
stops.add(new Stop(getOffset(i + 1, colors.size()), colors.get(i)));
}
LinearGradient lg = new LinearGradient(0, 0, 20, 20, false, CycleMethod.REPEAT, stops);
SVGPath svgPath = getSVGPath();
svgPath.setFill(lg);
svgPath.setStroke(lg);
return svgPath;
}
private SVGPath getNodeWithPattern() {
Image hatch = createCrossHatch();
ImagePattern pattern = new ImagePattern(hatch, 0, 0, 10, 10, false);
SVGPath svgPath = getSVGPath();
svgPath.setFill(pattern);
return svgPath;
}
private SVGPath getSVGPath() {
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
return svgPath;
}
private static Image createCrossHatch() {
Pane pane = new Pane();
pane.setPrefSize(20, 20);
Line fw = new Line(-5, -5, 25, 25);
Line bw = new Line(-5, 25, 25, -5);
fw.setStroke(Color.BLACK);
bw.setStroke(Color.BLACK);
fw.setStrokeWidth(3);
bw.setStrokeWidth(3);
pane.getChildren().addAll(fw, bw);
new Scene(pane);
SnapshotParameters sp = new SnapshotParameters();
return pane.snapshot(sp, null);
}
private double getOffset(double i, int count) {
return (((double) 1) / (double) count * (double) i);
}
And we get the desired result:

Java FX ComboBox drop down list

Can anyone tell me why some items from a dropdown list are not visible when running the jar application? It seems to happen randomly. I create an ObservableList, then recursively create a Line, assign it a stroke type from the observable list through a String as line.setStyle("-fx-stroke-dash-array:" + dashString + ";"). Finally, everything works fine and the ComboBox gets the whole list of line and a certain selection. But it sometimes fail to display lines in the dropdown list. The code is:
package test;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class ComboLines extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
ComboBox<Line> dashCombo = new ComboBox<>();
initDashLineCombo(dashCombo, dashUnit, 2);
dashCombo.getStylesheets().add("test/style.css");
dashCombo.setStyle("-fx-min-width: 100; -fx-max-width: 100; -fx-pref-width: 100; -fx-min-height: 15; -fx-pref-height: 15; -fx-max-height: 15;");
StackPane root = new StackPane();
root.getChildren().add(dashCombo);
primaryStage.setScene(new Scene(root, 150, 300));
primaryStage.show();
}
public static void initDashLineCombo(ComboBox<Line> cb, ObservableList<int[]> list, int i)
{
ArrayList<Line> LinesList = new ArrayList<>(); // to store lines
// cycle over the list and generate a line with dashing defined by list
for(int j = 0; j < list.size(); j++)
{
int sum = 0;
int[] dash = list.get(j);
String dashString = " ";
for(int k : dash) // cycle over an int array which defines the dashing
{ dashString += k + " ";
sum += k; }
System.out.println("sum = " + sum);
Line line = new Line(15, 0, 1*(15+sum), 0);
System.out.print("\ndashString :" + dashString);
// apply style
line.setStrokeWidth(2);// line width
line.setStroke(Color.BLACK);
line.setStyle("-fx-stroke-dash-array:" + dashString + ";"); // line dashing
LinesList.add(line); // collect the line
}
// create the observable list
final ObservableList<Line> LinesObs = FXCollections.observableArrayList(LinesList);
// set all line items in the combo box
cb.setItems(LinesObs);
// select an item ion the combo box
cb.setValue(LinesObs.get(i-1));
}
// ... dashing ...
int[] s10 = {1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,};
int[] s9 = {1,3,1,3,1,4,5,4,5,4, 1,3,1,3,1,4,5,4,5,4};
int[] s8 = {6,3,6,3,6,5,1,5, 6,3,6,3,6,5,1,5};
int[] s7 = {1,3,1,3,1,6,6,6, 1,3,1,3,1,6,6,6};
int[] s6 = {5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3};
int[] s5 = {5, 4, 5, 4, 1, 3, 1, 4, 5, 4, 5, 4, 1, 3, 1, 4};
int[] s4 = {5, 4, 1, 3, 1, 4, 5, 4, 1, 3, 1, 4, 5, 4, 1, 3, 1, 4};
int[] s3 = {5, 3, 1, 3, 5, 3, 1, 3, 5, 3, 1, 3, 5, 3, 1, 3};
int[] s2 = {15, 3, 15, 3, 15, 3};
int[] s1 = {60};
final ObservableList<int[]> dashUnit = FXCollections.observableArrayList(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
}
/* style.css */
.combo-box {
-fx-min-width: 35;
-fx-pref-width: 35;
-fx-max-width: 35;
-fx-min-height: 20;
-fx-pref-height: 20;
-fx-max-height: 20;
-fx-padding: -2 -8 -2 -5;
}
.combo-box-base > .arrow-button {
-fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0;
-fx-background-color: transparent;
-fx-alignment: center-left;
}
.combo-box .cell {
-fx-font-size: 8.75pt;
-fx-font-family: "Arial";
-fx-text-fill: BLACK;
-fx-alignment: BASELINE_RIGHT;
-fx-padding: 0 3 0 -5;
}
invisible lines
UPDATE: Using cell factory a simplified version (no CSS and no dashing applied) is like this. The same problem persists and further I cannot get the initial selection applied.
package test;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ComboLines extends Application
{
public static void main(String[] args) { launch(args); }
ComboBox<Line> dashCombo = new ComboBox<>();
#Override
public void start(Stage primaryStage)
{
StackPane root = new StackPane();
root.getChildren().add(dashCombo);
dashCombo.setItems(FXCollections.observableList(DASHUNIT));
dashCombo.getSelectionModel().selectFirst();
dashCombo.setCellFactory(new Callback<ListView<Line>, ListCell<Line>>()
{
#Override
public ListCell<Line> call(ListView<Line> newLine)
{
return new ListCell<Line>()
{
#Override
protected void updateItem(Line item, boolean y)
{
super.updateItem(item, false);
setGraphic(item);
} // end updateItem
} ; // end new ListCell
} // end call()
}); // end setCellFactory
primaryStage.setScene(new Scene(root, 150, 300));
primaryStage.show();
}
Line line1 = new Line(15, 0, 50, 0), line2 = new Line(15, 0, 50, 0), line3 = new Line(15, 0, 50, 0);
final ObservableList<Line> DASHUNIT = FXCollections.observableArrayList(line1, line2, line3);
}
Finally, I got it working with the code below. Following kleopatra's comments, the insipartion came from the official Oracle page https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ComboBox.html
ComboBox<Line> dashCombo = new ComboBox<>();
dashCombo.getStylesheets().add("style.css");
dashCombo.setStyle("-fx-min-width: 100; -fx-max-width: 100; -fx-pref-width: 100; "
+ "-fx-min-height: 15; -fx-pref-height: 15; -fx-max-height: 15;");
initDashLineCombo(dashCombo, common.General.DASHUNIT, (numberCoils - i), colCombo);
public static void initDashLineCombo(ComboBox<Line> cb, ObservableList<int[]> list, int i, ColorPicker cp)
{
for(int j = 0; j < list.size(); j++) // cycle over the list and generate a line with dashing defined by list
{
int[] dash = list.get(j);
String dashString = " ";
for(int k : dash)
dashString += k + " ";
Line line = new Line(25, 0, 95, 0);
line.setStrokeWidth(2); line.strokeProperty().bind(cp.valueProperty());
line.setStyle("-fx-stroke-dash-array:" + dashString + ";");
cb.getItems().add(line);
}
cb.getSelectionModel().clearAndSelect(i-1);
cb.setCellFactory(new Callback<ListView<Line>, ListCell<Line>>()
{
#Override public ListCell<Line> call(ListView<Line> p)
{
return new ListCell<Line>() {
private final Line line;
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
line = new Line(0, 0, 70, 0);
line.setStrokeWidth(2);
line.strokeProperty().bind(cp.valueProperty());
} // end Line
#Override protected void updateItem(Line item, boolean empty)
{
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
}
else {
line.setStyle(item.getStyle());
setGraphic(line);
setItem(line);
}
} // end updateItem()
}; // end ListCell
} // end call()
}); // end setCellFactory
}
enter image description here
enter image description here

JavaFX: Apply perspective transformation on a node given a perspective transformed pane

I made a small demo to exemplify the problem I am having. A walkthrough on its use:
1 - Click on the screen four times in order to create the grid.
2 - Click on the button at the bottom to give the created grid the perspective effect.
3 - Click on the screen again to draw a circle.
My problem is that I don't know what transformation I should apply on the Circle node in order to have the same visual effect as the grid at the exact location where the user clicked.
The demo at this point only draws a circle with no transformations.
The desired output is as it follows (I cheated here using an Ellipse instead of Circle - this cannot be my solution because the user inputs the four coordinates of the grid):
Here's the code for the demo.
Main.java
package application;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("View.fxml"));
Scene scene = new Scene(loader.load(), 600, 600);
primaryStage.setScene(scene);
primaryStage.setTitle("Perspective Transformation");
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
View.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="vBox" maxHeight="600.0" maxWidth="600.0" minHeight="600.0" minWidth="600.0" prefHeight="600.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<AnchorPane fx:id="anchorPane" maxHeight="575.0" minHeight="575.0" prefHeight="575.0" prefWidth="600.0" />
<Button fx:id="button" alignment="CENTER" mnemonicParsing="false" prefHeight="25.0" prefWidth="600.0" text="Perspective Transformation" />
</children>
</VBox>
Controller.java
package application;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
public class Controller {
#FXML
VBox vBox;
#FXML
AnchorPane anchorPane;
#FXML
Button button;
Line line_1, line_2, line_3, line_4, middle_1, middle_2;
private int numberOfClicks = 0;
private int W = 10;
//Store coordinates of the corresponding clicks
private double cx1, cy1,
cx2, cy2,
cx3, cy3,
cx4, cy4,
cx5, cy5;
#FXML
private void initialize() {
button.setDisable(true);
button.setOnAction((event) -> {
//Create a standard grid
Line standard_1 = new Line(0, 0, 0, 600);
Line standard_2 = new Line(0, 600, 600, 600);
Line standard_3 = new Line(600, 600, 600, 0);
Line standard_4 = new Line(600, 0, 0, 0);
//Middle ones
Line standard_5 = new Line(300, 0, 300, 600);
Line standard_6 = new Line(0, 300, 600, 300);
standard_1.setStrokeWidth(W);
standard_2.setStrokeWidth(W);
standard_3.setStrokeWidth(W);
standard_4.setStrokeWidth(W);
standard_5.setStrokeWidth(W);
standard_6.setStrokeWidth(W);
anchorPane.getChildren().clear();
Pane perspectivePane = new Pane();
perspectivePane.getChildren().addAll(standard_1, standard_2, standard_3,
standard_4, standard_5, standard_6);
PerspectiveTransform pt = new PerspectiveTransform();
pt.setUlx(cx1);
pt.setUly(cy1);
pt.setUrx(cx2);
pt.setUry(cy2);
pt.setLrx(cx3);
pt.setLry(cy3);
pt.setLlx(cx4);
pt.setLly(cy4);
perspectivePane.setEffect(pt);
anchorPane.getChildren().add(perspectivePane);
});
anchorPane.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
numberOfClicks++;
if(numberOfClicks == 1){
cx1 = event.getX();
cy1 = event.getY();
}
else if(numberOfClicks == 2){
cx2 = event.getX();
cy2 = event.getY();
line_1 = new Line(cx1, cy1, cx2, cy2);
line_1.setStrokeWidth(W);
anchorPane.getChildren().add(line_1);
}
else if(numberOfClicks == 3){
cx3 = event.getX();
cy3 = event.getY();
line_2 = new Line(cx2, cy2, cx3, cy3);
line_2.setStrokeWidth(W);
anchorPane.getChildren().add(line_2);
}
else if(numberOfClicks == 4){
cx4 = event.getX();
cy4 = event.getY();
line_3 = new Line(cx3, cy3, cx4, cy4);
line_4 = new Line(cx4, cy4, cx1, cy1);
line_3.setStrokeWidth(W);
line_4.setStrokeWidth(W);
middle_1 = new Line((cx1+cx2)/2, (cy1+cy2)/2, (cx3+cx4)/2, (cy3+cy4)/2);
middle_2 = new Line((cx2+cx3)/2, (cy2+cy3)/2, (cx4+cx1)/2, (cy4+cy1)/2);
middle_1.setStrokeWidth(W);
middle_2.setStrokeWidth(W);
anchorPane.getChildren().addAll(line_3, line_4, middle_1, middle_2);
button.setDisable(false);
}
else if(numberOfClicks == 5){
cx5 = event.getX();
cy5 = event.getY();
Circle circle = new Circle();
circle.setCenterX(cx5);
circle.setCenterY(cy5);
circle.setRadius(30);
circle.setFill(Color.TRANSPARENT);
circle.setStroke(Color.BLACK);
circle.setStrokeWidth(W);
//PerspectiveTransform pt = new PerspectiveTransform();
//What transformation should I apply to the circle?
//circle.setEffect(pt);
anchorPane.getChildren().add(circle);
}
else {
anchorPane.getChildren().clear();
numberOfClicks = 0;
}
}
});
}
}
I don't know for sure if this is what you wanted, but I used Group to accomplish this. I followed the code from here. Test this update. I will try explaining it tomorrow if it works.
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.control.Button;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
#FXML
VBox vBox;
#FXML
AnchorPane anchorPane;
#FXML
Button button;
Group group = new Group();
Group group2 = new Group();
PerspectiveTransform pt = new PerspectiveTransform();
Line line_1, line_2, line_3, line_4, middle_1, middle_2;
private int numberOfClicks = 0;
private int W = 10;
//Store coordinates of the corresponding clicks
private double cx1, cy1,
cx2, cy2,
cx3, cy3,
cx4, cy4,
cx5, cy5;
#Override
public void initialize(URL location, ResourceBundle resources)
{
button.setDisable(true);
anchorPane.getChildren().addAll(group);
button.setOnAction((event) -> {
pt.setUlx(cx1);
pt.setUly(cy1);
pt.setUrx(cx2);
pt.setUry(cy2);
pt.setLrx(cx3);
pt.setLry(cy3);
pt.setLlx(cx4);
pt.setLly(cy4);
group.setEffect(pt);
});
anchorPane.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
numberOfClicks++;
switch (numberOfClicks) {
case 1:
cx1 = event.getX();
cy1 = event.getY();
System.out.println(cx1 + " : " + cy1);
break;
case 2:
cx2 = event.getX();
cy2 = event.getY();
line_1 = new Line(cx1, cy1, cx2, cy2);
line_1.setStrokeWidth(W);
group.getChildren().add(line_1);
break;
case 3:
cx3 = event.getX();
cy3 = event.getY();
line_2 = new Line(cx2, cy2, cx3, cy3);
line_2.setStrokeWidth(W);
group.getChildren().add(line_2);
break;
case 4:
cx4 = event.getX();
cy4 = event.getY();
line_3 = new Line(cx3, cy3, cx4, cy4);
line_4 = new Line(cx4, cy4, cx1, cy1);
line_3.setStrokeWidth(W);
line_4.setStrokeWidth(W);
middle_1 = new Line((cx1 + cx2) / 2, (cy1 + cy2) / 2, (cx3 + cx4) / 2, (cy3 + cy4) / 2);
middle_2 = new Line((cx2 + cx3) / 2, (cy2 + cy3) / 2, (cx4 + cx1) / 2, (cy4 + cy1) / 2);
middle_1.setStrokeWidth(W);
middle_2.setStrokeWidth(W);
group.getChildren().addAll(line_3, line_4, middle_1, middle_2);
button.setDisable(false);
break;
case 5:
List<Double> centerOfTransform = findCenterOfTransForm(pt);
cx5 = event.getX();
cy5 = event.getY();
List<Double> list = new ArrayList();
list.add(cx5);
list.add(cy5);
List<Double> changeInCenterXAndCenterY = findChangeInCenterXAndY(centerOfTransform, list);
PerspectiveTransform ptCircle = new PerspectiveTransform();
ptCircle.setUlx(cx1 + changeInCenterXAndCenterY.get(0));
ptCircle.setUly(cy1 + changeInCenterXAndCenterY.get(1));
ptCircle.setUrx(cx2 + changeInCenterXAndCenterY.get(0));
ptCircle.setUry(cy2 + changeInCenterXAndCenterY.get(1));
ptCircle.setLrx(cx3 + changeInCenterXAndCenterY.get(0));
ptCircle.setLry(cy3 + changeInCenterXAndCenterY.get(1));
ptCircle.setLlx(cx4 + changeInCenterXAndCenterY.get(0));
ptCircle.setLly(cy4 + changeInCenterXAndCenterY.get(1));
System.out.println("cx5: " + cx5 + " cy5: " + cy5);
Circle circle = new Circle();
circle.setRadius(30);
circle.setFill(Color.TRANSPARENT);
circle.setStroke(Color.BLACK);
circle.setStrokeWidth(W);
circle.setCenterX(cx5);
circle.setCenterY(cy5);
circle.setEffect(ptCircle);
anchorPane.getChildren().add(circle);
System.out.println("centerx: " + circle.getTranslateX()+ " centery: " + circle.getTranslateY());
break;
default:
group.getChildren().clear();
numberOfClicks = 0;
break;
}
});
}
List<Double> findCenterOfTransForm(PerspectiveTransform pt)
{
List<Double> tempList = new ArrayList();
tempList.add((pt.getUlx() + pt.getUrx() + pt.getLrx() + pt.getLlx()) / 4);
tempList.add((pt.getUly() + pt.getUry() + pt.getLry() + pt.getLly()) / 4);
return tempList;
}
List<Double> findChangeInCenterXAndY(List<Double> originalXAndY, List<Double> newXAndY)
{
List<Double> tempList = new ArrayList();
tempList.add(newXAndY.get(0) - originalXAndY.get(0));
tempList.add(newXAndY.get(1) - originalXAndY.get(1));
return tempList;
}
}

JavaFX sizing listboxes in gridpane is it possible?

I am having some issues with sizing a listbox using a gridpane. Is it possible?? I need an actual rectangular box that is bigger than a single line. I am really hoping this is possible if it is not could you please give me some pointers. I am new to this and have been working at this for some time. Any help would be greatly appreciated. Thank you!!
What I have tried that didn't work--
list.setPrefWidth(100);
list.setPrefHeight(200);
package application;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
// Pane pane = new Pane();
GridPane pane = new GridPane();
pane.setAlignment(Pos.TOP_LEFT);
pane.setPadding(new Insets(20, 20, 20, 20));
pane.setHgap(5.5);
pane.setVgap(5.5);
final ComboBox<String> beverageComboBox = new ComboBox<String>();
beverageComboBox.getItems().addAll("Soda ", "Tea", "Coffee", "Mineral Water", "Juice",
"Milk");
final ComboBox<String> appetizerComboBox = new ComboBox<String>();
appetizerComboBox.getItems().addAll("Buffalo Wings ", "Buffalo Fingers", "Potato Skins", "Nachos",
"Mushroom Caps", "Shrimp Cocktail");
final ComboBox<String> maincourseComboBox = new ComboBox<String>();
maincourseComboBox.getItems().addAll("Seafood Alfredo ", "Chicken Alfredo", "Chicken Picatta", "Turkey Club",
"Lobster Pie", "Prime Rib", "Shrimp Scampi", "Turkey Dinner", "Stuffed Chicken");
final ComboBox<String> dessertComboBox = new ComboBox<String>();
dessertComboBox.getItems().addAll("Apple Pie ", "Sundae", "Carrot Cake", "Mud Pie", "Apple Crisp");
/*
* beverageComboBox.setValue("Soda"); appetizerComboB(ox.setValue(
* "Buffalo Wings"); maincourseComboBox.setValue("Seafood Alfredo");
* dessertComboBox.setValue("Apple Pie");
*/
Image image = new Image("fd.jpg");
pane.getChildren().add(new ImageView(image));
// -----------------------------------------------------------------------------------------------------------
Label tit = new Label("John's");
tit.setFont(Font.font("Tahoma", FontWeight.BOLD, 32));
pane.add(tit, 1, 0);
// ---------------------------------------------------------------------------------------------------------------
Label wi = new Label("Waiter Information");
wi.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
pane.add(wi, 0, 5);
Label tn = new Label("Table Number:");
pane.add(tn, 0, 6);
TextField tnf = new TextField();
pane.add(tnf, 1, 6);
Label wn = new Label("Waiter's Name:");
pane.add(wn, 0, 7);
TextField twn = new TextField();
pane.add(twn, 1, 7);
// ---------------------------------------------------------------------------------------------------------
Label mi = new Label("Menu Items");
mi.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
pane.add(mi, 0, 10);
Label b = new Label("Beverage:");
pane.add(b, 0, 11);
pane.add(beverageComboBox, 1, 11);
Label a = new Label("Appetizer:");
pane.add(a, 0, 12);
pane.add(appetizerComboBox, 1, 12);
Label mc = new Label("Main Course:");
pane.add(mc, 0, 13);
pane.add(maincourseComboBox, 1, 13);
Label d = new Label("Dessert:");
pane.add(d, 0, 14);
pane.add(dessertComboBox, 1, 14);
// ----------------------------------------------------------------------------------------------------------
Label bi = new Label("Bill");
bi.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
pane.add(bi, 0, 17);
Label st = new Label("Subtotal:");
pane.add(st, 0, 18);
TextField tst = new TextField();
pane.add(tst, 1, 18);
Label t = new Label("Tax:");
pane.add(t, 0, 19);
TextField tt = new TextField();
pane.add(tt, 1, 19);
Label to = new Label("Total:");
pane.add(to, 0, 20);
TextField tto = new TextField();
pane.add(tto, 1, 20);
// -----------------------------------------------------------------------------------------------------------
Label w = new Label("Waiter:");
pane.add(w, 0, 23);
TextField tw = new TextField();
pane.add(tw, 1, 23);
Label tn2 = new Label("Table Num:");
pane.add(tn2, 0, 24);
TextField ttn = new TextField();
pane.add(ttn, 1, 24);
// ------------------------------------------------------------------------------------------------------------
Button btn = new Button(" Clear Bill ");
pane.add(btn, 1, 30);
// -------------------------------------------------------------------------------------------------------------
Label io = new Label("Items Ordered");
io.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
pane.add(io, 2, 3);
// -----------------------------------------------------------------------------------------------------------------------
Label bo = new Label("Beverage Ordered");
pane.add(bo, 2, 5);
ListView<String> list = new ListView<>();
ObservableList<String> items = FXCollections.observableArrayList();
list.setItems(items);
pane.add(list, 3, 5);
// ---------------------------------------------------------------------------------------------------------------
Label ao = new Label("Appetizer Ordered");
pane.add(ao, 2, 7);
ListView<String> list2 = new ListView<>();
ObservableList<String> items2 = FXCollections.observableArrayList();
list2.setItems(items2);
pane.add(list2, 3, 7);
// ----------------------------------------------------------------------------------------------------------------
Label mco = new Label("Main Course Ordered");
pane.add(mco, 2, 11);
ListView<String> list3 = new ListView<>();
ObservableList<String> items3 = FXCollections.observableArrayList();
list3.setItems(items3);
pane.add(list3, 3, 11);
// -------------------------------------------------------------------------------------------------------------------
Label od = new Label("Dessert Ordered");
pane.add(od, 2, 13);
ListView<String> list4 = new ListView<>();
ObservableList<String> items4 = FXCollections.observableArrayList();
list4.setItems(items4);
pane.add(list4, 3, 13);
// Create a new scene and place it in the stage
Scene scene = new Scene(pane, 800, 800);
primaryStage.setTitle("Restaurant Bill Calculator");
primaryStage.setScene(scene);
primaryStage.show();
}
}

how to fit a gridpane in javafx2 accross the whole scene

I would like to fit the gridbox accross the whole scene as per attached picture and code below, however i cannot whatever I do!!
I have tried generating empty rows and columns but still does not fill, unless i add a lot.
I would like to specify a number of rows and columns and then let the program divide these equally along the screen, please help
how can I also locate the text inside the table the the right of the cell?
#Override public void start(Stage stage) {
timer.start();
buildData_timer.start();
Group root = new Group();
Scene scene = new Scene(root, 1180, 650);
stage.setScene(scene);
stage.setTitle("Separator Sample");
scene.getStylesheets().addAll(this.getClass().getResource("style.css").toExternalForm());
GridPane Mainpane = new GridPane();
scene.setRoot(Mainpane);
Mainpane.setGridLinesVisible(true);
Mainpane.setId("Mainpane");
GridPane prayertime_pane = new GridPane();
prayertime_pane.setId("prayertime_pane");
prayertime_pane.setGridLinesVisible(true);
prayertime_pane.setPadding(new Insets(20, 20, 20, 20));
prayertime_pane.setVgap(20);
prayertime_pane.setHgap(35);
HBox clock1Box = new HBox();
clock1Box.setSpacing(0);
clock1Box.getChildren().addAll(clock);
HBox fajrBox = new HBox();
fajrBox.setSpacing(0);
fajrBox.setMaxSize(155, 54);
fajrBox.getChildren().addAll(fajr_hourLeft, fajr_hourRight, time_Separator1, fajr_minLeft, fajr_minRight);
prayertime_pane.setConstraints(fajrBox, 0, 1);
prayertime_pane.getChildren().add(fajrBox);
HBox zuhrBox = new HBox();
zuhrBox.setSpacing(0);
zuhrBox.setMaxSize(155, 54);
zuhrBox.getChildren().addAll(zuhr_hourLeft, zuhr_hourRight, time_Separator2, zuhr_minLeft, zuhr_minRight);
prayertime_pane.setConstraints(zuhrBox, 0, 2);
prayertime_pane.getChildren().add(zuhrBox);
HBox asrBox = new HBox();
asrBox.setSpacing(0);
asrBox.setMaxSize(155, 54);
asrBox.getChildren().addAll(asr_hourLeft, asr_hourRight, time_Separator3, asr_minLeft, asr_minRight);
prayertime_pane.setConstraints(asrBox, 0, 3);
prayertime_pane.getChildren().add(asrBox);
HBox maghribBox = new HBox();
maghribBox.setSpacing(0);
maghribBox.setMaxSize(155, 54);
maghribBox.getChildren().addAll(maghrib_hourLeft, maghrib_hourRight, time_Separator4, maghrib_minLeft, maghrib_minRight);
prayertime_pane.setConstraints(maghribBox, 0, 4);
prayertime_pane.getChildren().add(maghribBox);
HBox ishaBox = new HBox();
ishaBox.setSpacing(0);
ishaBox.setMaxSize(155, 54);
ishaBox.getChildren().addAll(isha_hourLeft, isha_hourRight, time_Separator5, isha_minLeft, isha_minRight);
prayertime_pane.setConstraints(ishaBox, 0, 5);
prayertime_pane.getChildren().add(ishaBox);
TextFlow fajrtextFlow = new TextFlow();
Text text1 = new Text("الفجر\n");
text1.setId("prayer-text-arabic");
Text text10 = new Text("Fajr");
text10.setId("prayer-text-english");
fajrtextFlow.getChildren().addAll(text1, text10);
prayertime_pane.setConstraints(fajrtextFlow, 1, 1);
prayertime_pane.getChildren().add(fajrtextFlow);
TextFlow duhrtextFlow = new TextFlow();
Text text2 = new Text("الظهر\n");
text2.setId("prayer-text-arabic");
Text text20 = new Text("Duhr");
text20.setId("prayer-text-english");
duhrtextFlow.getChildren().addAll(text2,text20);
prayertime_pane.setConstraints(duhrtextFlow, 1, 2);
prayertime_pane.getChildren().add(duhrtextFlow);
TextFlow asrFlow = new TextFlow();
Text text3 = new Text("العصر\n");
text3.setId("prayer-text-arabic");
Text text30 = new Text("Asr");
text30.setId("prayer-text-english");
asrFlow.getChildren().addAll(text3,text30);
prayertime_pane.setConstraints(asrFlow, 1, 3);
prayertime_pane.getChildren().add(asrFlow);
TextFlow maghribFlow = new TextFlow();
Text text4 = new Text("المغرب\n");
text4.setId("prayer-text-arabic");
Text text40 = new Text("Maghrib");
text40.setId("prayer-text-english");
maghribFlow.getChildren().addAll(text4,text40);
prayertime_pane.setConstraints(maghribFlow, 1, 4);
prayertime_pane.getChildren().add(maghribFlow);
TextFlow ishaFlow = new TextFlow();
Text text5 = new Text("العشاء\n");
text5.setId("prayer-text-arabic");
Text text50 = new Text("Isha");
text50.setId("prayer-text-english");
ishaFlow.getChildren().addAll(text5,text50);
prayertime_pane.setConstraints(ishaFlow, 1, 5);
prayertime_pane.getChildren().add(ishaFlow);
final Separator sepHor = new Separator();
// sepHor.setAlignment(Pos.CENTER_LEFT);
// sepHor.setOrientation(Orientation.HORIZONTAL);
prayertime_pane.setConstraints(sepHor, 0, 1);
prayertime_pane.setColumnSpan(sepHor, 2);
prayertime_pane.getChildren().add(sepHor);
Mainpane.setConstraints(prayertime_pane, 2, 3);
Mainpane.getChildren().add(prayertime_pane);
Mainpane.setConstraints(clock1Box, 7, 1);
Mainpane.getChildren().add(clock1Box);
stage.show();
// stage.setFullScreen(true);
}
Try
ColumnConstraints c1 = new ColumnConstraints();
c1.setHgrow(Priority.ALWAYS);
ColumnConstraints c2 = new ColumnConstraints();
c2.setHgrow(Priority.NEVER);
Mainpane.getColumnConstraints().addAll(c1, c2);
RowConstraints r1 = new RowConstraints();
r1.setVgrow(Priority.NEVER);
RowConstraints r2 = new RowConstraints();
r2.setVgrow(Priority.ALWAYS);
Mainpane.getRowConstraints().addAll(r1, r2);
For more row/column/cell settings investigate GridPane, RowConstraints and ColumnConstraints.
However I suggest you to use AnchorPane or BorderPane here.

Resources