I tried to just make a simple Gridpane that would ask the user to input two numbers. For some reason the elements just went all over the place. I'm pretty sure I got the constraints correct.
This is my Settings class.
public class Settings {
public static void display() {
GridPane layout = new GridPane();
layout.setPadding(new Insets(10));
layout.setVgap(8);
layout.setHgap(10);
Scene scene = new Scene(layout, 600, 400);
//Title label
Label label = new Label("Settings");
GridPane.setConstraints(label, 1, 0);
//Minutes label
Label minutesLabel = new Label("Minutes:");
GridPane.setConstraints(minutesLabel, 0, 1);
//Minutes input
TextField minutesInput = new TextField();
minutesInput.setPromptText("minutes");
GridPane.setConstraints(minutesInput, 1, 1);
//Seconds label
Label secondsLabel = new Label("Seconds:");
GridPane.setConstraints(secondsLabel, 0, 2);
//Seconds input
TextField secondsInput = new TextField();
secondsInput.setPromptText("seconds");
GridPane.setConstraints(secondsInput, 1, 2);
//Ok button
Button okButton = new Button("Ok");
okButton.setOnAction(e -> {
try {
int minutes = Integer.parseInt(minutesInput.getText());
int seconds = Integer.parseInt(secondsInput.getText());
if(minutes > 59) minutes = 59;
else if(minutes < 1) minutes = 1;
if(seconds > 59) seconds = 59;
else if(seconds < 1) seconds = 1;
Main.updateMinsAndSecs(minutes, seconds);
Main.setSceneMain();
}catch(NumberFormatException numberFormatException) {
label.setText("Please enter valid number(s)");
}catch(FileNotFoundException fileNotFoundException) {
fileNotFoundException.printStackTrace();
}
});
okButton.setStyle("-fx-background-radius: 0;");
GridPane.setConstraints(secondsInput, 0, 3);
//Cancel button
Button cancelButton = new Button("Cancel");
cancelButton.setOnAction(e -> {
Main.setSceneMain();
});
cancelButton.setStyle("-fx-background-radius: 0;");
GridPane.setConstraints(secondsInput, 1, 3);
//Apply button
Button applyButton = new Button("Apply");
applyButton.setOnAction(e -> {
try {
int minutes = Integer.parseInt(minutesInput.getText());
int seconds = Integer.parseInt(secondsInput.getText());
if(minutes > 59) minutes = 59;
else if(minutes < 1) minutes = 1;
if(seconds > 59) seconds = 59;
else if(seconds < 1) seconds = 1;
Main.updateMinsAndSecs(minutes, seconds);
}catch(NumberFormatException numberFormatException) {
label.setText("Please enter valid number(s)");
}catch(FileNotFoundException fileNotFoundException) {
fileNotFoundException.printStackTrace();
}
});
applyButton.setStyle("-fx-background-radius: 0;");
GridPane.setConstraints(secondsInput, 2, 3);
layout.getChildren().addAll(label, minutesLabel, minutesInput, secondsLabel, secondsInput, okButton, cancelButton, applyButton);
Main.window.setScene(scene);
Main.window.setTitle("Settings");
}
}
This is how it turned out.
screenshot
I would like the solution to not use fxml.
Stackoverflow says my post is mostly code and I need more details so I'm also going to say that I have used a Gridpane to create a simple login screen and that one was pretty good. The code was basically the same except the positioning and the content.
You are setting different constraints to secondsInput instead of okButton, cancelButton and applyButton:
GridPane.setConstraints(secondsInput, 1, 2);
GridPane.setConstraints(secondsInput, 0, 3);
GridPane.setConstraints(secondsInput, 1, 3);
GridPane.setConstraints(secondsInput, 2, 3);
Instead of:
GridPane.setConstraints(secondsInput, 1, 2);
GridPane.setConstraints(okButton, 0, 3);
GridPane.setConstraints(cancelButton, 1, 3);
GridPane.setConstraints(applyButton, 2, 3);
Related
I am almost done with this here program. It is one of them work order forms with event handlers and an updated total. How may I return a total value updated after receiving user input? I am sure I need a return pane somewhere, just not sure where. Code below:
public class Working_order extends Application {
// Radio buttons
private RadioButton rbNext = new RadioButton("$20");
private RadioButton rbThis = new RadioButton("$12");
private RadioButton rbSome = new RadioButton("$5");
private Label lbDue = new Label("$0.00");
#Override
public void start(Stage primaryStage) {
// Create a pane and set its properties
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setPadding(new Insets(11.5, 12.5, 13.5, 14.5));
pane.setHgap(5.5);
pane.setVgap(5.5);
// Place nodes in the pane
pane.add(new Label("Item"), 0, 0);
pane.add(tfItem, 1, 0);
pane.add(new Label("Price"), 0, 1);
pane.add(tfPrice, 1, 1);
pane.add(new Label("Quantity"), 0, 2);
pane.add(tfQty, 1, 2);
CheckBox chTaxable = new CheckBox("Taxable?");
pane.add(chTaxable, 1, 3);
// More nodes in a pane
pane.add(new Label("Shipping"), 0, 4);
pane.add(rbNext, 1, 5);
pane.add(new Label("Next Day"), 0, 5);
pane.add(rbThis, 1, 6);
pane.add(new Label("This Week"), 0, 6);
pane.add(rbSome, 1, 7);
pane.add(new Label("Total Due"), 0, 8);
pane.add(lbDue, 1, 8);
pane.add(new Label("Some Day"), 0, 7);
Button btAdd = new Button("Process");
Button btAdd2 = new Button("Reset");
// Toggle group
ToggleGroup group = new ToggleGroup();
rbNext.setToggleGroup(group);
rbThis.setToggleGroup(group);
rbSome.setToggleGroup(group);
btAdd.setOnAction(e -> {
// read textboxes
String sPrice = tfPrice.getText();
double price = Double.parseDouble(sPrice);
int qty = Integer.parseInt(tfQty.getText());
double subTotal = price * qty;
double tax;
if (chTaxable.isSelected()) {
tax = subTotal * 0.07;
} else {
tax = 0;
}
});
pane.add(btAdd, 0, 9);
pane.add(btAdd2, 1, 9);
GridPane.setHalignment(btAdd, HPos.RIGHT);
GridPane.setHalignment(btAdd2, HPos.LEFT);
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("ShowGridPane"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display
}
public static void main(String[] args) {
launch(args);
}
}
First of all, you didn't construct the text fields (tfItem,tfPrice,tfQty).
to solve this add those lines
TextField tfItem = new TextField();
TextField tfPrice = new TextField();
TextField tfQty = new TextField();
your problem is simple, after calculating the result by applying your formula in the btAdd (process button) event handler just add this line at the end of the event handler
lbDue.setText( result + "" );
this shall solve your issue
I am trying to change the text of a Button in a GridPane when the Button is clicked. I have successfully managed to do so. but, I am getting this exception.
I have this function that changes the text.
public void clicker(Button b) {
if (b.getText().equals(" ")) {
if (turn == 0) {
b.setText("X");
b.setFont(Font.font("Times", FontWeight.EXTRA_BOLD,
60));
turn = 1;
} else if (turn == 1) {
Button bNew = new Button("Y");
bNew.setFont(Font.font("Times", FontWeight.EXTRA_BOLD, 60));
b.setText("Y");
b.setFont(Font.font("Times", FontWeight.EXTRA_BOLD,
60));
turn = 0;
}
}
}
this is the pane set up and event handler where the errors are happening.
GridPane pane = new GridPane();
b1.setMinSize(100, 100);
b2.setMinSize(100, 100);
b3.setMinSize(100, 100);
b4.setMinSize(100, 100);
b5.setMinSize(100, 100);
b6.setMinSize(100, 100);
b7.setMinSize(100, 100);
b8.setMinSize(100, 100);
b9.setMinSize(100, 100);
GridPane.setConstraints(b1, 0, 0);
GridPane.setConstraints(b2, 1, 0);
GridPane.setConstraints(b3, 2, 0);
GridPane.setConstraints(b4, 0, 1);
GridPane.setConstraints(b5, 1, 1);
GridPane.setConstraints(b6, 2, 1);
GridPane.setConstraints(b7, 0, 2);
GridPane.setConstraints(b8, 1, 2);
GridPane.setConstraints(b9, 2, 2);
pane.getChildren().addAll(b1, b2, b3, b4, b5, b6, b7, b8, b9);
b1.setOnAction((event) -> {
clicker(b1);
pane.getChildren().add(b1);
});
b2.setOnAction((event) -> {
clicker(b2);
pane.getChildren().add(b2);
});
any help would be appreciated. thanks
I'm trying to make a somewhat slider puzzle kind of game where you click 1 image, then click another and they swap positions. For some reason this works correctly the first time you do it, but when you go to swap an image for the second time and every time after that it selects a different element than the one that you clicked on. Any help would be appreachated, thank you.
public class test extends Application {
int click1 = -1, click2 = -1;
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
//Create a GridPane
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setHgap(5);
pane.setVgap(5);
//create ArrayList and add imageList to ArrayList
ArrayList<ImageView>imageList = new ArrayList<ImageView>();
for (int i = 0; i < 9; i++) {
imageList.add(new ImageView ((i) +".jpg"));
}
addImages(imageList, pane);
//add onClick listeners to each image
imageList.get(0).setOnMouseClicked(e->{
swap(0, imageList, pane);
});
imageList.get(1).setOnMouseClicked(e->{
swap(1, imageList, pane);
});
imageList.get(2).setOnMouseClicked(e->{
swap(2, imageList, pane);
});
imageList.get(3).setOnMouseClicked(e->{
swap(3, imageList, pane);
});
imageList.get(4).setOnMouseClicked(e->{
swap(4, imageList, pane);
});
imageList.get(5).setOnMouseClicked(e->{
swap(5, imageList, pane);
});
imageList.get(6).setOnMouseClicked(e->{
swap(6, imageList, pane);
});
imageList.get(7).setOnMouseClicked(e->{
swap(7, imageList, pane);
});
imageList.get(8).setOnMouseClicked(e->{
swap(8, imageList, pane);
});
//display the scene
Scene scene = new Scene(pane, 650, 650);
primaryStage.setScene(scene);
primaryStage.setTitle("Test");
primaryStage.show();
}
private void swap(int lastClick, ArrayList<ImageView> imageList, GridPane pane) {
if (click1 == -1) {
click1 = lastClick;
System.out.println(imageList.get(click1).getImage().impl_getUrl()+ " ");
imageList.get(click1).setScaleX(1.02);
imageList.get(click1).setScaleY(1.02);
} else {
click2 = lastClick;
System.out.println(imageList.get(click2).getImage().impl_getUrl()+ " ");
//swap indexes in ArrayList
Collections.swap(imageList, click2, click1);
pane.getChildren().removeAll(imageList);
addImages(imageList, pane);
//reset everything for next swap
imageList.get(click1).setScaleX(1.0);
imageList.get(click1).setScaleY(1.0);
imageList.get(click2).setScaleX(1.0);
imageList.get(click2).setScaleY(1.0);
click1 = -1;
click2 = -1;
}
}
private void addImages(ArrayList<ImageView> imageList, GridPane pane) {
//add imageList to the GridPane
int i = 0;
while (i < 9) {
for (int j = 0; j <= 2; j++) {
for (int k = 0; k <= 2; k++) {
pane.add(imageList.get(i), k, j);
i++;
}
}
}
}
}
You need to update the mouseclick listener once you update the new element. What ends up happening is a stale state. An item that has moved reports its initial position rather than its actual position, resulting in your items moving around to where they shouldn't be.
Basic State.
0, 1, 2, 3, 4, 5, 6, 7, 8
Assume we click 3 and then 5. The request is to swap image 5 to image 3's slot, and image 3 to image 5's slot.
0, 1, 2, 5, 4, 3, 6, 7, 8
This looks right for now, but let's try another swap. Let's swap image 1 with 5.
0, 3, 2, 5, 4, 1, 6, 7, 8
What happened?! 1 and 5 were clicked, but 3 and 1 swapped places instead!
The move on the back-end worked actually worked exactly as designed. Image 5 and Image 1 were clicked, resulting in the operation "swap slot 5 with slot 1, instead of the intended slot 3 with slot 1. The issue with that is that the image in slot 5 is actually image 3.
The rectification for this is to update the mouse click listeners to know where they are afterwards, so they can report their new, updated positions.
Fix would be:
imageList.get(click1).setOnMouseClicked(e->{
swap(click1, imageList, pane);
});
imageList.get(click2).setOnMouseClicked(e->{
swap(click2, imageList, pane);
});
This tells the swapped items that "This is where you are moved, and from now on you should report that this is your new moved position."
The solution is probably staring at me in the face. But here's my problem.
Take a look at this method:
public void showUserData() {
int numUsers = usersModel.numberOfUsers(); // number of users(rows) in the database
ColumnConstraints column1 = new ColumnConstraints();
column1.setPercentWidth(40);
ColumnConstraints column2 = new ColumnConstraints();
column2.setPercentWidth(60);
int counter = 0;
for(int i = 0; i <= numUsers - 1; i++) {
subGrid = new GridPane();
subGrid.getColumnConstraints().addAll(column1, column2);
userImage = new ImageView();
subGrid.setStyle("-fx-background-color: #dddddd;");
subGrid.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
System.out.println("mouse click detected! " + mouseEvent.getSource());
subGrid.setStyle("-fx-background-color: blue;");
}
});
vbox = new VBox();
vbox.getChildren().add(new Label("Name: " + getUserData().get(counter)));
vbox.getChildren().add(new Label("Username: " + getUserData().get(counter + 1)));
vbox.getChildren().add(new Label("Position: " + getUserData().get(counter + 2)));
subGrid.add(vbox, 1, 0);
user = new Image("file:///" + getUserImage().get(i));
userImage.setFitWidth(150);
userImage.setFitHeight(150);
userImage.setSmooth(true);
userImage.setPreserveRatio(true);
userImage.setImage(user);
subGrid.add(userImage, 0, 0);
if(i % 2 == 0 && i == 0) {
mainGrid.add(subGrid, 0, 0);
} else if (i % 2 == 0 && i != 0){
mainGrid.add(subGrid, 0, i - 1);
} else {
mainGrid.add(subGrid, 1, i - 1);
}
scroll.setContent(mainGrid);
counter = counter + 3;
}
}
I know its a mess but hear me out. I have a ScrollPane, and inside is a GridPane that spans the entire area of the ScrollPane. In every cell of the GridPane, there is another smaller GridPane. In each of these smaller GridPanes, the left column is an ImageView and the right is a VBox with labels in it.
The long and the short of this method is that:
a. It takes the number of rows in the database.
b. It creates a subGrid for every row in the database (corresponding to the number of users in the table).
c. It creates the ImageViews and VBoxes for each of the subGrids and adds them in.
d. It then takes the subGrids and adds it to the mainGrid.
This process works. But the listener only works on the latest subGrid that was added. i.e. second subGrid lights up, first does not, third subGrid lights up, second does not, etc.
I'm not sure if TableView can work with this. That's why I tried it with GridPane first. Why does my listener not work?
I ama beginner at this. I know the method is a mess. I know I need to refactor some things. But as long, as I can get this to work, I will happily clean it up afterwards. Any help appreciated, thank you.
So I have this button. It can be pressed with the enter key, and can be selected through tabbing to it, but it cannot be clicked on, and doesn't appear to exist as far as the cursor is concerned. I don't believe anything is covering it, but it most be covered some how, as a button created with identical code is clickable.
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Mortgage Calculator");
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setHgap(10);
pane.setVgap(10);
pane.setPadding(new Insets(25, 25, 25, 25));
Scene scene = new Scene(pane, 350, 325);
Text sceneTitle = new Text("Mortgage Calculator");
sceneTitle.setFont(Font.font("Arial", FontWeight.NORMAL, 20));
pane.add(sceneTitle, 0, 0, 2, 1);
Label total = new Label("Value of your Mortgage:");
pane.add(total, 0, 1);
final TextField totalField = new TextField();
pane.add(totalField, 1, 1);
Label percent = new Label("% Interest:");
pane.add(percent, 0, 2);
final TextField percentField = new TextField();
pane.add(percentField, 1, 2);
Label time = new Label("Length of mortgage:");
pane.add(time, 0, 3);
final TextField timeField = new TextField();
pane.add(timeField, 1, 3);
final Text amountOwed = new Text();
pane.add(amountOwed, 1, 7);
final Text payment = new Text();
pane.add(payment, 1, 8);
Button calculateButton = new Button("Calculate");
HBox hbox1 = new HBox(10);
hbox1.setAlignment(Pos.BOTTOM_RIGHT);
hbox1.getChildren().add(calculateButton);
calculateButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
double principal = Double.parseDouble(totalField.getText());
double interest = (Double.parseDouble(percentField.getText()) / 100) / 12;
int time = Integer.parseInt(timeField.getText());
int numPayment = time * 12;
double monthlyPayment = (principal * (interest * (Math.pow((interest + 1), numPayment)))) / (Math.pow((1 + interest), numPayment) - 1);
//double totalPayment = ;
//amountOwed.setText("Amount owed is: " + totalPayment);
payment.setText("Monthly payment is: $" + (int)Math.ceil(monthlyPayment));
}
});
pane.add(hbox1, 1, 4);
Button clearButton = new Button("Clear");
HBox hbox = new HBox(10);
hbox.setAlignment(Pos.BOTTOM_LEFT);
hbox.getChildren().add(clearButton);
pane.add(hbox, 1, 4);
EventHandler<ActionEvent> handler1 = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
totalField.setText("");
percentField.setText("");
timeField.setText("");
payment.setText("");
}
};
clearButton.setOnAction(handler1);
primaryStage.setScene(scene);
primaryStage.show();
}
}
mouseTransparent Issue
You put the "Calculate" button in a HBox and then you call setMouseTransparent(true) on the HBox. Such a call will disable mouse input on the HBox and all it's children. This behavior is documented in the linked Javadoc:
If true, this node (together with all its children) is completely transparent to mouse events. When choosing target for mouse event, nodes with mouseTransparent set to true and their subtrees won't be taken into account.
You don't need the setMouseTransparent(true) call; just remove it, and the "Calculate" button will be clickable as you expect.
Overlapping Components Issue
You also need to ensure that you don't overlap some components with others otherwise only the top components will be clickable. In your case, the HBox containing the "Clear" button is overlapping the "Calculate" button.
So change:
pane.add(hbox, 1, 4);
To:
pane.add(clearButton, 1, 4);
Debugging Assistance
You can debug layouts either by calling layout.setStyle("-fx-background-color: green;") to show the extent of the layout, or by using ScenicView.