My program takes a user value and passes the value through a method before returning a message on the GUI. I am wondering how I could be able to recursively move this message (called displayResult) value down along the Y axis in order to make room for new messages when the user calls the method again.
public class GuessingGameController extends Tab {
Scene sceneOne;
Scene sceneTwo;
int choice;
int generatedNumber;
//private GuessingGame resetGuessingGame;
public int generateRandomNumber() {
Random randomNumber = new Random();
int number = randomNumber.nextInt(50) + 1;
return number;
}
GuessingGameController(Stage primaryStage) {
GuessingGame guess = new GuessingGame();
generatedNumber = generateRandomNumber();
Label labelOne = new Label("WELCOME TO THE GUESSING GAME");
setText("GuessingGame");
Pane paneLayoutOne = new StackPane();
Pane paneLayoutTwo = new StackPane();
Button playButton = new Button("Click to Play!");
Button quitButton = new Button("Quit");
paneLayoutOne.getChildren().addAll(labelOne, playButton, quitButton);
labelOne.setTranslateX(0);
labelOne.setTranslateY(-100);
playButton.setTranslateX(0);
playButton.setTranslateY(0);
quitButton.setTranslateX(0);
quitButton.setTranslateY(50);
setContent(paneLayoutOne);
sceneOne = new Scene(paneLayoutOne, 400, 400);
quitButton.setOnAction(e -> System.exit(0));
playButton.setOnAction(e -> primaryStage.setScene(sceneTwo));
Label userMessage = new Label("Please enter your guess here");
TextField userInput = new TextField();
Button guessButton = new Button("Guess");
Button resetButton = new Button("Reset Game");
Button backButton = new Button("Back");
userMessage.setTranslateX(0);
userMessage.setTranslateY(-160);
userInput.setTranslateX(0);
userInput.setTranslateY(-120);
guessButton.setTranslateX(0);
guessButton.setTranslateY(-80);
resetButton.setTranslateX(0);
resetButton.setTranslateY(-40);
backButton.setTranslateX(0);
backButton.setTranslateY(0);
guessButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
int choice = Integer.parseInt(userInput.getText());
guess.startGuessingGame(choice, generatedNumber);
String endResult;
endResult = guess.startGuessingGame(choice, generatedNumber);
Label displayResult = new Label(endResult);
displayResult.setTranslateX(0);
displayResult.setTranslateY(150);
paneLayoutTwo.getChildren().add(0, displayResult);
}
});
//resetButton.setOnAction(e -> resetGuessingGame.resetForm(this));
backButton.setOnAction(e -> primaryStage.setScene(sceneOne));
paneLayoutTwo.getChildren().addAll(userMessage, userInput, guessButton, resetButton, backButton);
sceneTwo = new Scene(paneLayoutTwo, 400, 400);
}
}
Related
I have the following code
Image img = new Image(getClass().getResource("1.png").toExternalForm(), tg.getWidth(), tg.getHeight(), false, true, true);
ImageView view = new ImageView(img);
tg.setGraphic(view);
(where tg is a toggle button)
and I get this
I want the image to fit perfectly into the button but whatever I do I'm unable to accomplish this. I've already tried using view.setFit methods but it doesn't seem to have any effect
Edit:
This is the code that creates the GridPane
this.gameBoard = new GridPane();
this.gameBoard.setPrefSize(600, 600);
this.gameCards = new ToggleButton[this.boardSize * this.boardSize];
EventHandler<ActionEvent> cardSelectedHandler = this::onCardSelected;
for (int i = 0; i < this.gameCards.length; i++) {
this.gameCards[i] = new ToggleButton;
this.gameCards[i].setPrefSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
this.gameCards[i].setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
this.gameCards[i].setOnAction(cardSelectedHandler);
this.gameBoard.add(this.gameCards[i], i % this.boardSize, i / this.boardSize);
GridPane.setHgrow(this.gameCards[i], Priority.ALWAYS);
GridPane.setVgrow(this.gameCards[i], Priority.ALWAYS);
}
private void onCardSelected(ActionEvent event) {
ToggleButton tg = (ToggleButton) event.getTarget();
Image img = new Image(getClass().getResource("1.png").toExternalForm(), tg.getWidth(), tg.getHeight(), false, true, true);
ImageView view = new ImageView(img);
tg.setGraphic(view);
EDIT 2:
doing some change
private void onCardSelected(ActionEvent event) {
ToggleButton tg = (ToggleButton) event.getTarget();
Image img = new Image(getClass().getResource("1.png").toExternalForm());
ImageView view = new ImageView(img);
view.setFitHeight(150);
view.setFitWidth(150);
view.setPreserveRatio(false);
tg.setAlignment(Pos.TOP_LEFT);
tg.setGraphic(view);
I now get
but I still get this button resize
Sorry, I have just begun learning javaFX and cannot figure out how to get all of my icons on buttons the same size. I tried a couple things but could not get it working, all help is appreciated. Thank you!
Wont let me post my question unless I add more details but I cant think of anything else to put so just ignore this whole paragraph as I ramble on so I can post my question and continue coding my game.
public class Main extends Application {
Stage window;
Button button;
Scene scene1, scene2;
public static final int ROCK = 0;
public static final int PAPER = 1;
public static final int SCISSORS = 2;
public static int userChoice;
public static void main(String [] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception
{
window = primaryStage;
//Layout 1
VBox layout = new VBox(20);
Label label = new Label("Rock Paper Scissors");
Button myButton = new Button("Start");
myButton.setOnAction(e -> window.setScene(scene2));
Button exit = new Button("Exit");
exit.setOnAction(e -> System.exit(0));
layout.getChildren().addAll(label, myButton, exit);
layout.setAlignment(Pos.CENTER);
scene1 = new Scene(layout, 300, 300);
//Layout 2
BorderPane border = new BorderPane();
VBox layout1 = new VBox(10);
Label label1 = new Label("Choose One");
layout1.setAlignment(Pos.CENTER);
//Layout 3
HBox layout2 = new HBox(10);
//Rock Image Button
Image rockIm = new Image(getClass().getResourceAsStream("Rock2.png"));
Button rock = new Button();
rock.setGraphic(new ImageView(rockIm));
rock.setOnAction(e -> userChoice = ROCK);
//Paper Image Button
Image paperIm = new
Image(getClass().getResourceAsStream("Paper2.png"));
Button paper = new Button();
paper.setGraphic(new ImageView(paperIm));
paper.setOnAction(e -> userChoice = PAPER);
//Scissor Image Button
Image scissorIm = new
Image(getClass().getResourceAsStream("Scissor2.png"));
Button scissors = new Button();
scissors.setGraphic(new ImageView(scissorIm));
scissors.setOnAction(e -> userChoice = SCISSORS);
Button quit = new Button("Return");
quit.setOnAction(e -> window.setScene(scene1));
layout2.getChildren().addAll(rock, paper, scissors, quit);
layout2.setAlignment(Pos.CENTER);
scene2 = new Scene(layout2, 300, 300);
window.setTitle("Rock Paper Scissors");
window.setScene(scene1);
window.show();
}
}
I've so far done this, it's adding labels on the stage but removing thing is working but not as intended...
How can I store data of labels in an array or something so I can compare the remove.getText(); with that and delete that typed value if previous added as a label on stage.
public class Main extends Application {
Group root;
Label label1,label;
int count=1,count1=1;
public static void main(String[] args) {launch(args);}
public void start(Stage stage) throws Exception {
stage.setTitle("LinkedList GUI");
stage.setResizable(false);
root = new Group();
LinkedList<Integer> Linked =new LinkedList<Integer>();
Button Addfirst = new Button("AddFirst");
Addfirst.setTranslateX(40);
Addfirst.setTranslateY(350);
TextField first=new TextField();
first.setPrefWidth(60);
first.setTranslateX(120);
first.setTranslateY(350);
Addfirst.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
int a = Integer.parseInt(first.getText());
Linked.addFirst(a);
label1=new Label(" "+first.getText());
label1.setFont(Font.font("Buxton Sketch",FontWeight.BOLD,FontPosture.ITALIC,12));
label1.setPrefWidth(25);
label1.setPrefHeight(25);
label1.setTranslateY(60);
label1.setTextFill(Color.GREEN );
label1.setStyle("-fx-border-color: Blue;");
root.getChildren().addAll(label1);
label1.setTranslateX(250-(20*count++));
count++;
}
});
Button Addlast = new Button("AddLast");
Addlast.setTranslateX(200);
Addlast.setTranslateY(350);
TextField last=new TextField();
last.setPrefWidth(60);
last.setTranslateX(270);
last.setTranslateY(350);
Addlast.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
int b= Integer.parseInt(last.getText());
Linked.addLast(b);
label=new Label(" "+last.getText());
label.setFont(Font.font("Buxton Sketch",FontWeight.BOLD,FontPosture.ITALIC,12));
label.setPrefWidth(25);
label.setPrefHeight(25);
label.setTranslateY(60);
label.setTextFill(Color.GREEN );
label.setStyle("-fx-border-color: Blue;");
root.getChildren().add(label);
label.setTranslateX(250+(20*count1++));
count1++;
}
});
Button delete = new Button("Delete");
delete.setTranslateX(350);
delete.setTranslateY(350);
TextField remove=new TextField();
remove.setPrefWidth(60);
remove.setTranslateX(420);
remove.setTranslateY(350);
delete.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
if(remove.getText().equals(first.getText())) {
Linked.remove(first.getText());
root.getChildren().remove(label1);
}
else if(remove.getText().equals(last.getText())) {
Linked.remove(last.getText());
root.getChildren().remove(label);
}
else {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setContentText("Not in List");
alert.showAndWait();
}
}
});
Text text =new Text("Doubly LinkedList GUI");
text.setStyle("-fx-border-color: Blak;");
text.setFont(Font.font("Buxton Sketch",FontWeight.BOLD,FontPosture.ITALIC,16));
text.setTranslateX(150);
text.setTranslateY(30);
root.getChildren().addAll(text,Addfirst,first,Addlast,last,delete,remove);
Scene scene = new Scene(root,500,400);
stage.setScene(scene);
stage.show();
}
}
I recommend using a layout that positions the children for you instead of positioning them yourself. E.g. using a HBox as parent for the labels allows you to simply add/remove the child at the same index as the one added/removed in the list:
#Override
public void start(Stage stage) throws Exception {
HBox container = new HBox(20);
container.setPrefHeight(40);
Button addFirst = new Button("add head");
Button addLast = new Button("add tail");
Button remove = new Button("remove");
TextField textField = new TextField();
HBox buttonContainer = new HBox(10, textField, addFirst, addLast, remove);
final LinkedList<Integer> list = new LinkedList<>();
addFirst.setOnAction(evt -> {
String text = textField.getText();
Integer value = Integer.parseInt(text);
list.addFirst(value);
container.getChildren().add(0, new Label(text));
});
addLast.setOnAction(evt -> {
String text = textField.getText();
Integer value = Integer.parseInt(text);
list.addLast(value);
container.getChildren().add(new Label(text));
});
remove.setOnAction(evt -> {
String text = textField.getText();
int value = Integer.parseInt(text);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
Integer element = iterator.next();
if (element == value) {
container.getChildren().remove(iterator.nextIndex() - 1);
iterator.remove();
break;
}
}
});
VBox root = new VBox(container, buttonContainer);
Scene scene = new Scene(root, 500, 400);
stage.setScene(scene);
stage.show();
}
I have a method inside of one of my controllers that requires some seconds to process. I would like to have a gif animation popup while this occurs but I only get a static image. This is my code:
#FXML
public void search(ActionEvent e) {
final Stage dialog = new Stage();
Group popup = new Group();
Image image = new Image("file:resources/images/bender.gif");
ImageView view = new ImageView(image);
popup.getChildren().add(view);
Scene dialogScene = new Scene(popup);
dialog.setScene(dialogScene);
dialog.show();
Platform.runLater(new Runnable() {
#Override
public void run() {
Match msg = stablishSearchConditions();
TreeItem<String> root = new TreeItem<>("ROOT");
int indexName = 1;
String mensaje = "Mensaje ";
treeLabelResults.setText("");
arbol.setRoot(root);
for (Match message : msg.each()) {
TreeItem<String> nodo = new TreeItem<String>(mensaje + indexName);
root.getChildren().add(nodo);
root.setExpanded(true);
String mens = message.getMessage();
TreeItem<String> nodo2 = new TreeItem<String>(mens);
nodo.getChildren().add(nodo2);
indexName++;
}
dialog.close();
}
});
}
You are blocking the fx application thread by running the expensive operation on this thread. This prevents your UI from updating, including animating the GIF.
Move the expensive operations to a non-application thread instead and only use Platform.runLater() to "commit" the ui updates:
Runnable expensiveTask = () -> {
// expensive operations that should not run on the application thread
Match msg = stablishSearchConditions();
TreeItem<String> root = new TreeItem<>("ROOT");
int indexName = 1;
String mensaje = "Mensaje ";
for (Match message : msg.each()) {
TreeItem<String> nodo = new TreeItem<String>(mensaje + indexName);
root.getChildren().add(nodo);
root.setExpanded(true);
String mens = message.getMessage();
TreeItem<String> nodo2 = new TreeItem<String>(mens);
nodo.getChildren().add(nodo2);
indexName++;
}
// update ui -> application thread
Platform.runLater(() -> {
treeLabelResults.setText("");
arbol.setRoot(root);
dialog.close();
});
};
// start new thread for expensiveTask
new Thread(expensiveTask).start();
I created this very simple example for JavaFX alert dialog for JavaFX8u40.
public class MainApp extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
private Stage stage;
#Override
public void start(Stage primaryStage) throws Exception
{
Button create = new Button("Create Alert");
create.setTooltip(new Tooltip("Create an Alert Dialog"));
create.setOnAction(e ->
{
createAlert();
});
primaryStage.setScene(new Scene(create));
primaryStage.show();
stage = primaryStage;
}
protected Alert createAlert()
{
Alert alert = new Alert(AlertType.WARNING);
Image image1 = new Image("http://www.mcaprojecttraining.com/images/java-big-icon.png");
ImageView imageView = new ImageView(image1);
alert.setGraphic(imageView);
alert.initModality(Modality.APPLICATION_MODAL);
alert.initOwner(stage);
alert.getDialogPane().setContentText("Some text");
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> System.out.println("The alert was approved"));
return alert;
}
}
I'm interested how I can set the image on the left side of the dialog.
Did someone manage to change the side of the image?
If you have a look at how the header is constructed, you'll find a GridPane node to layout a Label on the left and a StackPane for the icon.
If you want to reverse the cells order by code, you can do it, but it will be overriden every time updateHeaderArea() is called.
My suggestion is using this public API:
dialogPane.setHeader(Node header);
dialogPane.setGraphic(Node graphic);
providing a header with an icon on the left and a label, and a null graphic.
Using the same approach as DialogPane, we could add another GridPane as header:
protected Alert createAlert(){
Alert alert = new Alert(AlertType.WARNING);
alert.initModality(Modality.APPLICATION_MODAL);
alert.initOwner(stage);
alert.getDialogPane().setContentText("Some text");
DialogPane dialogPane = alert.getDialogPane();
GridPane grid = new GridPane();
ColumnConstraints graphicColumn = new ColumnConstraints();
graphicColumn.setFillWidth(false);
graphicColumn.setHgrow(Priority.NEVER);
ColumnConstraints textColumn = new ColumnConstraints();
textColumn.setFillWidth(true);
textColumn.setHgrow(Priority.ALWAYS);
grid.getColumnConstraints().setAll(graphicColumn, textColumn);
grid.setPadding(new Insets(5));
Image image1 = new Image("http://www.mcaprojecttraining.com/images/java-big-icon.png");
ImageView imageView = new ImageView(image1);
imageView.setFitWidth(64);
imageView.setFitHeight(64);
StackPane stackPane = new StackPane(imageView);
stackPane.setAlignment(Pos.CENTER);
grid.add(stackPane, 0, 0);
Label headerLabel = new Label("Warning");
headerLabel.setWrapText(true);
headerLabel.setAlignment(Pos.CENTER_RIGHT);
headerLabel.setMaxWidth(Double.MAX_VALUE);
headerLabel.setMaxHeight(Double.MAX_VALUE);
grid.add(headerLabel, 1, 0);
dialogPane.setHeader(grid);
dialogPane.setGraphic(null);
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> System.out.println("The alert was approved"));
return alert;
}
And this is what you will see: