I want to make a little game in JavaFX, but when I click on the start Button, Java(TM) Platform SE binary is crashing!
package sample;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.effect.Bloom;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import java.util.Random;
public class Main extends Application {
#Override
public void start(Stage primaryStage){
Weiter weiter = new Weiter(true);
Random rand = new Random();
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setVgap(10);
grid.setHgap(10);
grid.setPadding(new Insets(10, 10, 10,10));
Rectangle ra = new Rectangle(120, 120);
ra.setFill(Color.LIGHTBLUE);
ra.setStroke(Color.BLACK);
ra.setStrokeWidth(2);
ra.setEffect(new Bloom());
grid.add(ra, 1, 0);
Button start = new Button("start");
grid.add(start, 0, 3);
TextField feld = new TextField();
grid.add(feld, 1, 3);
Button btnBest = new Button("ok");
grid.add(btnBest, 3, 3);
start.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (weiter.getWeiter()){
int wiedhol = rand.nextInt(101);
while (wiedhol == 0){
wiedhol = rand.nextInt(101);
}
System.out.println(wiedhol);
for(int i = 0; i <= wiedhol; i++){
try {
ra.setFill(Color.BLUE);
Thread.sleep(1000);
ra.setFill(Color.LIGHTBLUE);
}catch(InterruptedException ie){}
}
}
}
});
primaryStage.setScene(new Scene(grid, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Class Weiter:
package sample;
public class Weiter {
private boolean weiter;
public Weiter(boolean wert){
this.weiter = wert;
}
public boolean getWeiter(){
return weiter;
}
public void setWeiter(boolean wert){
this.weiter = wert;
}
}
Actually when I press the start Button it should make a Random Number and the Rectangle is turning Blue until the random number is reached. then you have to enter the number you counted and when it's right you won.
It does not crash.
Notice this:
for(int i = 0; i <= wiedhol; i++){
try {
ra.setFill(Color.BLUE);
Thread.sleep(1000);
ra.setFill(Color.LIGHTBLUE);
}catch(InterruptedException ie){}
}
That thread.sleep() halts your program.
Related
I'm making a javafx app and when I run it the IDE gives no errors. The application window doesn't show but I can see that the program's running in task manager.
I have tried running the code in both Eclipse and IntelliJ.
I tried running a new application with just a title and it worked so it's something to do with the particular code.
package main;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.text.Font;
public class Main extends Application {
public boolean isX=true;
public Button[] bs=new Button[9];
Label turn = new Label("Turn: X");
public int i=0;
public void start(Stage stage){
BorderPane bp = new BorderPane();
bp.setPrefSize(310, 350);
turn.setFont(Font.font(20));
bp.setTop(turn);
makeButtons(bs);
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.add(bs[0],0,0);
grid.add(bs[1],1,0);
grid.add(bs[2],2,0);
grid.add(bs[3],0,1);
grid.add(bs[4],1,1);
grid.add(bs[5],2,1);
grid.add(bs[6],0,2);
grid.add(bs[7],1,2);
grid.add(bs[8],2,2);
bp.setCenter(grid);
stage.setScene(new Scene(bp));
stage.setTitle("Tic tac toe");
stage.show();
}
void makeButtons(Button[] bs){
while (i<bs.length){
bs[i]=new Button(" ");
bs[i].setFont(Font.font("Monospaced", 40));
bs[i].setPrefSize(90, 90);
bs[i].setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (isX){
isX=false;
bs[i].setText("X");
turn.setText("Turn: O");
} else {
isX=true;
bs[i].setText("O");
turn.setText("Turn: X");
}
}
});
}
}
public static void main(String[] args){
launch(Main.class);
}
}
Update: I finished noughts and crosses
package main;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.text.Font;
public class Main extends Application {
public boolean isX=true;
public Button[] bs=new Button[9];
Label turn = new Label("Turn: X");
int goes =0;
public void start(Stage stage){
BorderPane bp = new BorderPane();
bp.setPrefSize(310, 350);
turn.setFont(Font.font(20));
bp.setTop(turn);
makeButtons(bs);
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.add(bs[0],0,0);
grid.add(bs[1],1,0);
grid.add(bs[2],2,0);
grid.add(bs[3],0,1);
grid.add(bs[4],1,1);
grid.add(bs[5],2,1);
grid.add(bs[6],0,2);
grid.add(bs[7],1,2);
grid.add(bs[8],2,2);
bp.setCenter(grid);
stage.setScene(new Scene(bp));
stage.setTitle("Noughts and crosses");
stage.show();
}
void makeButtons(Button[] bs){
for (int i=0;i<bs.length;i++){
bs[i]=new Button(" ");
bs[i].setFont(Font.font("Monospaced", 40));
bs[i].setPrefSize(90, 90);
bs[i].setOnAction(this::handleTurn);
}
}
private void handleTurn(ActionEvent e){
goes++;
if (goes>4&&won()){
return;
}
Button b = (Button) e.getSource();
if (!b.getText().equals(" ")){
return;
}
if (isX) {
isX = false;
b.setText("X");
turn.setText("Turn: O");
} else {
isX=true;
b.setText("O");
turn.setText("Turn: X");
}
if (goes==9){
turn.setText("Game over: not turns left");
}
}
private boolean won(){
//rows
for (int i=0;i< 7;i+=3){
if (!bs[i].getText().equals(" ")&&bs[i].getText().equals(bs[i+1].getText())&&bs[i].getText().equals(bs[i+2].getText())){
turn.setText(bs[i].getText()+" wins!");
return true;
}
}
//columns
for (int i=0;i<3;i++){
if (!bs[i].getText().equals(" ")&&bs[i].getText().equals(bs[i+3].getText())&&bs[i].getText().equals(bs[i+6].getText())){
turn.setText(bs[i].getText()+" wins!");
return true;
}
}
//diagonals
if (!bs[0].getText().equals(" ")&&bs[0].getText().equals(bs[4].getText())&&bs[0].getText().equals(bs[8].getText())){
turn.setText(bs[0].getText()+" wins!");
return true;
}
if (!bs[2].getText().equals(" ")&&bs[2].getText().equals(bs[4].getText())&&bs[2].getText().equals(bs[6].getText())){
turn.setText(bs[2].getText()+" wins!");
return true;
}
return false;
}
public static void main(String[] args){
launch(Main.class);
}
}
You aren't changing the value of i in the while loop in method makeButtons and therefore the while loop never terminates.
Also, you should add an action listener to the buttons and not a mouse listener. Refer to this tutorial.
Consider the following code.
(Note: More explanations after the code.)
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.text.Font;
public class Main extends Application {
public boolean isX=true;
public Button[] bs=new Button[9];
Label turn = new Label("Turn: X");
public void start(Stage stage){
BorderPane bp = new BorderPane();
bp.setPrefSize(310, 350);
turn.setFont(Font.font(20));
bp.setTop(turn);
makeButtons(bs);
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.add(bs[0],0,0);
grid.add(bs[1],1,0);
grid.add(bs[2],2,0);
grid.add(bs[3],0,1);
grid.add(bs[4],1,1);
grid.add(bs[5],2,1);
grid.add(bs[6],0,2);
grid.add(bs[7],1,2);
grid.add(bs[8],2,2);
bp.setCenter(grid);
stage.setScene(new Scene(bp));
stage.setTitle("Tic tac toe");
stage.show();
}
void makeButtons(Button[] bs){
int i = 0;
while (i<bs.length){
bs[i]=new Button(" ");
bs[i].setFont(Font.font("Monospaced", 40));
bs[i].setPrefSize(90, 90);
bs[i].setOnAction(this::handleTurn);
i++;
}
}
private void handleTurn(ActionEvent event) {
Button button = (Button) event.getSource();
if (isX) {
isX = false;
button.setText("X");
turn.setText("Turn: O");
}
else {
isX = true;
button.setText("O");
turn.setText("Turn: X");
}
}
public static void main(String[] args){
launch(Main.class);
}
}
The above code uses method references which were introduced in Java 8. Here is the relevant line from the above code:
bs[i].setOnAction(this::handleTurn);
Whenever any of the buttons are clicked, method handleTurn is executed.
Notice that, in that method, I obtain the actual button that was clicked by calling method getSource (of class ActionEvent).
This is how it looks when I run the above code.
Here my code (In Java on Eclipse) displays 3 random cards from the a file. I am trying to get a shuffle button to work and randomly shuffle in 3 new cards. I used "Collections.shuffle(cards);" and passed it my boolean array but it says I can't because it wants a List<> list. Is it possible to get the shuffle to work with my boolean or would I have to use a List?
Here is my code:
import java.util.Collections;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
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.stage.Stage;
public class DisplayCards extends Application {
HBox imageViews;
#Override
public void start(Stage primaryStage) throws Exception {
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
boolean[] cards = new boolean[52];
int count = 0;
while(count <3) {
int card = (int)(Math.random() * 52);
if(!cards[card]) {
cards[card] = true;
pane.add(new ImageView(new Image("card/" + (card) + ".png")), count, 0);
count++;
}
}
imageViews = new HBox();
imageViews.setAlignment(Pos.CENTER);
shuffle();
Button btnShuffle = new Button("Shuffle");
btnShuffle.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
shuffle();
}
});
BorderPane Bpane = new BorderPane();
Bpane.setCenter(imageViews);
Bpane.setBottom(btnShuffle);
Scene scene = new Scene(pane, 250, 150);
primaryStage.setTitle("Display 4 Cards");
primaryStage.setScene(scene);
primaryStage.show();
}
private void shuffle() {
Collections.shuffle(cards);
}
public static void main(String[] args) {
launch(args);
}
}
You can implement the Fisher–Yates shuffle for an array.
private void shuffle(){
for(int i = cards.length - 1; i > 0; i--){
int j = java.util.concurrent.ThreadLocalRandom.current().nextInt(i + 1);
boolean temp = cards[i];
cards[i] = cards[j];
cards[j] = temp;
}
}
I need some help if you can spare a few minutes.
I am in a bit of a pickle as I try to make this work.
I have a javaFX class like this
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class FoorballTeam extends Application {
int i1=0;
int i3=0;
String[] PlayerNames = new String[12];
int[] goals = new int[12];
#Override
public void start(Stage primaryStage) {
player[] playerData = new player[12];
Button btn = new Button();
btn.setText("add Player");
GridPane root = new GridPane();
root.add(btn,0,0);
int i2;
for (i2=0;i2<=11;i2++)
{playerData[i2]=new player();}
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
playerData[i3].player(root, i3);
i3++;
}
});
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public String[] getPlayerNames() {
return PlayerNames;
}
public void setPlayerNames(String[] PlayerNames) {
this.PlayerNames = PlayerNames;
}
public int[] getGoals() {
return goals;
}
public void setGoals(int[] goals) {
this.goals = goals;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
and a second class named player like this
import javafx.event.EventType;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
public class player {
String NameOfPlayer = new String();
int goalsOfPlayer;
public void player (GridPane root,int numberOfPlayer)
{
TextField name = new TextField();
TextField goals = new TextField();
GridPane grid = new GridPane();
grid.add(name,0,0);
grid.add(goals,1,0);
root.add(grid,0,numberOfPlayer+1);
System.out.println("player " + numberOfPlayer + " added");
name.textProperty().addListener((observable, oldValue, newValue) -> {
NameOfPlayer=newValue;
});
goals.textProperty().addListener((observable, oldValue, newValue) -> {
goalsOfPlayer=Integer.parseInt(newValue);
});
}
}
I want every time that I make a change to a players name or goals to pass this change on the two arrays PlayerNames[] and goals[] of the main class.
for example if player1 changes goals from 1 to 2 I want the goals[1]=2.
Also is it possible to put a listener to this two arrays so when a player changes name or goals to trigger the listener.
Any help will be appreciated.
One simple solution is to warp the int[] array with an observable list, and listen to changes in this list :
import java.util.Arrays;
import java.util.Random;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class ListenToArrayCahnges extends Application {
private final int SIZE = 12;
private final Integer[] goals = new Integer[SIZE];
private final Random rand = new Random();
private int counter = 0;
#Override
public void start(Stage primaryStage) {
Arrays.fill(goals, 0); //initial values
//Warp array with an observable list. list back by array so it is of fixed length
ObservableList<Integer> goalsList = FXCollections.observableArrayList(Arrays.asList(goals));
//add listener to list
goalsList.addListener((ListChangeListener<Integer>) c ->{
//respond to list changes
System.out.println("Goals changed to : "+ goalsList);
});
//button to change the list
Button btn = new Button();
btn.setText("Add goal");
btn.setOnAction(event -> {
goalsList.set(counter, rand.nextInt(100));
counter = ++counter % SIZE ; //increment counter 0,1,2....11 and back to 0
});
GridPane root = new GridPane();
root.add(btn,0,0);
Scene scene = new Scene(root, 150, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Note that the posted mcve represents the problem that needs to be solved (or in this case a solution to it), and not the specific application or use case.
I'm trying to use the Magnifier from jfxtras-labs 2.2 to see more details on an image. At the same time, I want to draw a rectangle on top of this image. The problem is, that the Magnifier blocks all other events.
Here is my sample code:
package magnifiertest;
import java.io.File;
import javax.imageio.ImageIO;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import jfxtras.labs.scene.control.Magnifier;
public class TestMagnifier extends Application {
Group groupForRectangles;
ImageView pageImageView;
private boolean new_rectangle_is_being_drawn;
private Rectangle new_rectangle;
private double starting_point_x;
private double starting_point_y;
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
groupForRectangles = new Group();
groupForRectangles = new Group();
pageImageView = new ImageView();
pageImageView.setPreserveRatio(true);
pageImageView.setFitHeight(800);
pageImageView.setFitWidth(600);
pageImageView.setImage(SwingFXUtils.toFXImage(ImageIO.read(new File("/sample/Penguins.jpg")), null));
groupForRectangles.setOnMouseDragged(event -> {
setOnMouseDragged(event);
});
groupForRectangles.setOnMousePressed(event -> {
setOnMousePressed(event);
});
groupForRectangles.setOnMouseReleased(event -> {
setOnMouseReleased(event);
});
//If you outcomment the following lines, the rectangle drawing works
Magnifier m = new Magnifier(pageImageView);
groupForRectangles.getChildren().add(pageImageView);
groupForRectangles.getChildren().add(m);
root.getChildren().add(groupForRectangles);
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
public void setOnMousePressed(MouseEvent event) {
System.out.println("mouse pressed");
if (new_rectangle_is_being_drawn == false) {
starting_point_x = event.getX();
starting_point_y = event.getY();
System.out.println(starting_point_x + " ; " + starting_point_y);
groupForRectangles.getChildren().remove(new_rectangle);
new_rectangle = new Rectangle();
new_rectangle.setFill(Color.TRANSPARENT);
new_rectangle.setStroke(Color.BLACK);
groupForRectangles.getChildren().add(new_rectangle);
new_rectangle_is_being_drawn = true;
}
}
public void setOnMouseDragged(MouseEvent event) {
if (new_rectangle_is_being_drawn == true) {
double current_ending_point_x = event.getX();// - sub.getLayoutX();
double current_ending_point_y = event.getY();// - sub.getLayoutY();
adjust_rectangle_properties(starting_point_x, starting_point_y, current_ending_point_x,
current_ending_point_y, new_rectangle);
}
}
public void setOnMouseReleased(MouseEvent event) {
if (new_rectangle_is_being_drawn == true) {
new_rectangle.setFill(Color.TRANSPARENT);
new_rectangle_is_being_drawn = false;
}
}
void adjust_rectangle_properties(double starting_point_x, double starting_point_y, double ending_point_x,
double ending_point_y, Rectangle given_rectangle) {
given_rectangle.setX(starting_point_x);
given_rectangle.setY(starting_point_y);
given_rectangle.setWidth((ending_point_x - starting_point_x));
given_rectangle.setHeight((ending_point_y - starting_point_y));
if (given_rectangle.getWidth() < 0) {
given_rectangle.setWidth(-given_rectangle.getWidth());
given_rectangle.setX(given_rectangle.getX() - given_rectangle.getWidth());
}
if (given_rectangle.getHeight() < 0) {
given_rectangle.setHeight(-given_rectangle.getHeight());
given_rectangle.setY(given_rectangle.getY() -
given_rectangle.getHeight());
}
}
}
Thanks.
This is a fan program where use a slider to increase and decrease the speed of the fan. I do not need the increase and decrease button, I only have them as a guide to help the slider figure out what happens when you scroll left or right. I will delete those later. My slider is not showing and I can't test it out. Where did I go wrong here?
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.control.Slider;
public class module2 extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
// Create fan pane
FanPane fanPane = new FanPane(100);
Slider mSlider = new Slider();
HBox scrollPane = new HBox(mSlider);
KeyFrame keyFrame = new KeyFrame(Duration.millis(10), e-> fanPane.spin());
Timeline fanTimeline = new Timeline(keyFrame);
fanTimeline.setCycleCount(Timeline.INDEFINITE);
// Buttons pause, resume, increase, decrease, reverse
Button pause = new Button("Pause");
pause.setOnAction(e-> fanTimeline.pause());
Button resume = new Button("Resume");
resume.setOnAction(e-> fanTimeline.play());
//fanPane.increase()
Button increase = new Button("Increase");
increase.setOnAction(e -> {
fanTimeline.setRate(fanTimeline.getCurrentRate() + 1);
mSlider.setValue(fanTimeline.getCurrentRate());
});
Button decrease = new Button("Decrease");
decrease.setOnAction(e -> {
fanTimeline.setRate(
(fanTimeline.getCurrentRate() - 1 < 0) ? 0 : fanTimeline.getCurrentRate() - 1);
mSlider.setValue(fanTimeline.getCurrentRate());
});
Button reverse = new Button("Reverse");
reverse.setOnAction(e-> fanPane.increment *= -1);
HBox hButtons = new HBox(pause,resume,reverse);
hButtons.setSpacing(10);
hButtons.setAlignment(Pos.CENTER);
hButtons.setPadding(new Insets(10, 10, 10, 10));
BorderPane borderPane = new BorderPane(fanPane, null, null, hButtons, null);
primaryStage.setScene(new Scene(borderPane));
primaryStage.setTitle("Spinning fan");
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private class FanPane extends Pane {
private Circle c;
private Arc[] blades = new Arc[4];
private double increment = 1;
Slider mSlider = new Slider();
HBox scrollPane = new HBox(mSlider);
FanPane(double radius) {
setMinHeight(400);
setMinWidth(400);
c = new Circle(200,200,radius,Color.BLUE);
c.setStroke(Color.BLACK);
double bladeRadius = radius * 0.9;
for (int i = 0; i < blades.length; i++) {
blades[i] = new Arc(
c.getCenterX(), c.getCenterY(), // center point
bladeRadius, bladeRadius, // X and Y radius
(i * 90) + 30, 35); // start angle and length
blades[i].setFill(Color.YELLOW);
blades[i].setType(ArcType.ROUND);
}
getChildren().addAll(c);
getChildren().addAll(blades);
}
private void spin() {
for (Arc blade : blades) {
double prevStartAngle = blade.getStartAngle();
blade.setStartAngle(prevStartAngle + increment);
}
}
}
}