My JavaFx code does not work as it should do. I am trying to create 10X10 text matrix populated with either a 1 or 0, so it looks similar to a 2d array filled with 1's and 0's. When I put the code that is currently in the MatrixPane class in main it works fine, but with this code it just sets the scene but it looks like no pane is added or created.
If anyone can help me I would greatly appreciate it.
I realize I have Imported some unused things, I am using them for other parts of the program.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.FlowPane;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javafx.scene.shape.Arc;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.geometry.Pos;
import javafx.collections.ObservableList;
public class Button1 extends Application
{
public void start(Stage primaryStage)
{
GridPane pane = new GridPane();
MatrixPane Matrix = new MatrixPane();
pane.getChildren().add(Matrix);
Scene scene = new Scene(pane, 700, 500);
primaryStage.setTitle("1 window "); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args)
{
Application.launch(args);
}
}
class MatrixPane extends Pane
{
double HEIGHT = 500;
double WIDTH = 200;
private GridPane pane1 = new GridPane();
public MatrixPane()
{
}
public void fillmatrix()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
TextField text = new TextField(Integer.toString((int)(Math.random() * 2)));
text.setMinWidth(WIDTH / 8.0);
text.setMaxWidth(WIDTH / 10.0);
text.setMinHeight(HEIGHT / 8.0);
text.setMaxHeight(HEIGHT / 10.0);
this.pane1.add(text, j, i);
}
}
}
}
Call fillMatrix(); method from Button1.start()
Add GridPane to MatrixPane in MatrixPane construcor
private GridPane pane1 = new GridPane();
public MatrixPane() {
getChildren().add(pane1);
}
This will work.
Well I checked your code and you are excessively using GridPane. First you have a class named MatrixPane which inherits Pane, but also this class has a property GridPane. Finally, you use GridPane once again to add MatrixPane!
So, what I did is to use composition, but first I change the start method
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
MatrixPane Matrix = new MatrixPane();
//pane.getChildren().add(Matrix);
Matrix.fillmatrix();
Scene scene = new Scene(Matrix.getPane1(), 700, 500);
...
So here the scene is going to receive the data of pane1, this attribute has the values stored when fillmatrix was called.
Then I add the getter method in MatrixPane for the attribute pane1
class MatrixPane {
double HEIGHT = 500;
double WIDTH = 200;
private GridPane pane1 = new GridPane();
public GridPane getPane1() {
return pane1;
}
...
Related
I am trying to use a text field to get an input which represents the radius to draw a circle.
I have tried creating the circle inside processreturn.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
public class Task5 extends Application {
int rad;
int x = 200;
private TextField input;
public void start(Stage stage) {
input = new TextField();
input.setPrefWidth(50);
input.setAlignment(Pos.CENTER);
input.setOnAction(this::processReturn);
System.out.print(rad);
Circle circle = new Circle();
// Setting the properties of the circle
circle.setCenterX(x);
circle.setCenterY(200);
circle.setRadius(rad);
// Creating a Group object
Group root = new Group(circle, input);
// Creating a scene object
Scene scene = new Scene(root, 600, 300, Color.LIGHTBLUE);
// Setting title to the Stage
stage.setTitle("Drawing a Circle");
// Adding scene to the stage
stage.setScene(scene);
// Displaying the contents of the stage
stage.show();
System.out.print(rad);
}
public void processReturn(ActionEvent event) {
rad = Integer.parseInt(input.getText());
System.out.println("rad is" + rad);
}
}
Currently it seems that the variable rad is changing but it is not updating the circle in the Group instance. Is it possible to update the group or create another group that has a the circle with the updated rad?
I'm new to javaFX and I wanted to make a simple code that counted how many times a person pressed a button and displayed the count on the application itself. Currently I have my code printing the counter in my IDE and would just like to some how attach it to the scene(eg I click run and every time I click the button it prints how many times I've clicked it in my workbench). I looked around stack overflow and youtube but the closest I got to what I was looking for was printing it in my IDE. Thanks for any help.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JavaFXTest extends Application {
private int counter = 0;
public static void main (String [] args){
Application.launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
stage = primaryStage;
Pane pane = new Pane();
pane.setPrefSize(400,400);
Button button = new Button("Smash it!");
HBox root = new HBox(5, pane);
button.setOnAction(e -> {
counter();
});
root.getChildren().add(button);
Scene scene1 = new Scene(root,1000, 800, Color.AQUA);
stage.setScene(scene1);
stage.setTitle("ButtonSmash!");
stage.show();
}
public void counter(){
counter++;
System.out.println(counter);
}
}
Here is the full code:
package StackOverFlow;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JavaFXTest extends Application {
private int counter = 0;
private Label label = new Label("Count: ");
public static void main (String [] args){
Application.launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
stage = primaryStage;
Pane pane = new Pane();
pane.setPrefSize(400,400);
Button button = new Button("Smash it!");
HBox root = new HBox(5, pane);
button.setOnAction(e -> {
label.setText("Count: "+Integer.toString(counter));
counter();
});
root.getChildren().add(button);
label.relocate(0, 0); // You can put this label, wherever you want!
root.getChildren().add(label);
Scene scene1 = new Scene(root,1000, 800, Color.AQUA);
stage.setScene(scene1);
stage.setTitle("ButtonSmash!");
stage.show();
}
public void counter(){
counter++;
//System.out.println(counter);
}
}
You had to make one label and to add it to your pane.getChildren();
And whenever you press the button you need to change text from that label.
I am making a simple game on JavaFX right now.
The picture of my program is here
So far, my code is generating random monsters using a random number generator, and my health will decrease a random number each time I hit the explore button.
I also added a stats box. This box will display my current health, hunger, and hydration levels.
My problem is, is that I am not sure how I am supposed to change the values in my stats box. Every time my character gets hit by a monster, I want the health text to change. When I do :
dStatBox.setText(mainCharacter.getHealthLevel());
It says that I must convert the int to a string. How can I go about doing this?
My whole code is below:
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class Game extends Application {
public static TextArea dialogue = new TextArea();
public static TextArea dStatBox = new TextArea();
Button exploreButton;
Random r = new Random();
int ogreDamage = r.nextInt(20) + 1;
public void start(Stage primaryStage) {
Character mainCharacter = new Character("Nikki");
BorderPane pane = new BorderPane();
HBox top = new HBox();
VBox gameBox = new VBox();
VBox explore = new VBox();
VBox statBox = new VBox();
exploreButton = new Button("Explore");
Label stats = new Label("Stats");
stats.setFont(Font.font(30));
stats.setFont(Font.font("Helvetica", FontWeight.BOLD, FontPosture.REGULAR, 24));
statBox.setPadding(new Insets(10,10,10,10));
statBox.setSpacing(10);
statBox.setMaxHeight(300);
statBox.setPrefWidth(300);
statBox.getChildren().addAll(stats, dStatBox);
statBox.setAlignment(Pos.TOP_CENTER);
dStatBox.setEditable(false);
dStatBox.setText("Health: 100/100\n");
Label label = new Label("Game Dialogue");
label.setFont(Font.font(30));
label.setFont(Font.font("Helvetica", FontWeight.BOLD, FontPosture.REGULAR, 24));
gameBox.setPadding(new Insets(10,10,10,10));
gameBox.setSpacing(10);
dialogue.setMaxHeight(200);
dialogue.setMaxWidth(470);
dialogue.setWrapText(true);
dialogue.setEditable(false);
gameBox.getChildren().addAll(label, dialogue, exploreButton);
gameBox.setAlignment(Pos.CENTER);
top.getChildren().addAll(gameBox, statBox);
top.setAlignment(Pos.TOP_LEFT);
pane.setTop(top);
dialogue.appendText("Welcome to Wild Berries - the Ultimate Survival Game\n");
dialogue.appendText("How long can you survive for? Only time will tell...\n");
exploreButton.setOnAction(e -> {
Random r = new Random();
int ogreDamage = r.nextInt(20) + 1;
int randomInt = r.nextInt(3) + 1;
dialogue.appendText("You begin to explore the wild...\n");
if(randomInt == 1) {
dialogue.appendText("A wild Ogre has appeared!\n");
dialogue.appendText("You have been hurt. -" + ogreDamage + " HP.\n");
mainCharacter.setHealthLevel(mainCharacter.getHealthLevel() - ogreDamage);
dialogue.appendText(mainCharacter.getHealthLevel());
if(mainCharacter.getHealthLevel() <= 0) {
dialogue.appendText("You have died. Thank you for playing.");
}
}
if(randomInt == 2) {
dialogue.appendText("A wild Goblin has appeared!\n");
}
if(randomInt == 3) {
dialogue.appendText("A wild Ghost has appeared!\n");
}
});
Scene scene = new Scene(pane, 800, 450);
primaryStage.setScene(scene);
primaryStage.setTitle("Wild Berries GUI");
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
I'm assuming that mainCharacter.getHealthLevel() is returning an int. You should do dStatBox.setText("Health: " + mainCharacter.getHealthLevel());
As simple as this:
int healthLevel = mainCharacter.getHealthLevel();
String.valueOf(healthLevel);
//or
Integer.toString(healthLevel);
I'm trying to make a Suduko board in JavaFX. I heard TilePane is especially good for this because the entire idea behind TilePane is that each 'Tile' is of uniform size. Great, that's exactly how a Suduko board, chess board, checkers, Tic Tac Toe, Battleship, etc. Sounds like TilePane is the must have pane for any kind of board game app.
Or is it?
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.image.Image;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SudukoSolver extends Application
{
Stage window;
Scene scene;
private final int TEXTFIELD_WIDTH = 32;
private final int TEXTFIELD_HEIGHT = 32;
#Override public void start(Stage window) throws Exception
{
this.window = window;
window.setTitle("Suduko Solver");
window.setOnCloseRequest(e -> closeProgram());
// Does setting this to false defeat the purpose of TilePane?
window.setResizable(false);
VBox root = new VBox();
//root.setAlignment(Pos.CENTER);
TilePane tiles = new TilePane();
tiles.setAlignment(Pos.CENTER);
// Does not appear to do anything.
tiles.setPrefColumns(9);
tiles.setPrefRows(9);
// Add all the tiles to the Pane.
root.getChildren().add(tiles);
for (int i = 0; i < 81; i++)
{
TextField textBox = new TextField();
textBox.setMinHeight(TEXTFIELD_HEIGHT);
textBox.setMaxHeight(TEXTFIELD_HEIGHT);
textBox.setMinWidth(TEXTFIELD_WIDTH);
textBox.setMaxWidth(TEXTFIELD_WIDTH);
textBox.setTextFormatter(new TextFormatter<String>((Change change) ->
{
String newText = change.getControlNewText();
if (newText.length() > 1)
{
return null ;
}
else if (newText.matches("[^1-9]"))
{
return null;
}
else
{
return change ;
}
}));
tiles.getChildren().add(textBox);
}
scene = new Scene(root, 600, 750);
window.setScene(scene);
window.show();
}
/**
* This method is called when the user wishes to close the program.
*/
private void closeProgram()
{
Platform.exit();
}
public static void main(String[] args)
{
launch(args);
}
}
Notice how clearly this is not a 9x9 grid.
Any help would be greatly appreciated. Thank you!
In your code the width of your TilePane is determided by the parent VBox rather than by the prefColumns property of the TilePane.
From the javadoc of prefColumns:
This value is used only to compute the preferred size of the tilepane and may not reflect the actual number of rows columns, which may change if the tilepane is resized to something other than its preferred height width.
(Some errors in the doc fixed by me.)
You need to use a parent that doesn't resize the TilePane. (VBox resizes it's children by default.) Use VBox.setFillWidth to change this behaviour:
root.setFillWidth(false);
I want to create a refresh button for my webView that will be on top of the view (even if it hides part of the view), when I place the button on the Grid Pane it pushes the webView down or to the side (depends where I place the button)
How can I place my "refresh" button on top of the webView and not move it aside?
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class webviewbrowser extends Application {
#Override public void start(Stage primaryStage) throws Exception {
Pane root = new WebViewPane();
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.setFullScreen(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
/**
* Create a resizable WebView pane
*/
public class WebViewPane extends Pane {
public WebViewPane() {
VBox.setVgrow(this, Priority.ALWAYS);
setMaxWidth(Double.MAX_VALUE);
setMaxHeight(Double.MAX_VALUE);
WebView view = new WebView();
view.setMinSize(500, 400);
view.setPrefSize(500, 400);
final WebEngine eng = view.getEngine();
eng.load("http://google.com");
//final TextField locationField = new TextField("http://www.google.com");
//locationField.setMaxHeight(Double.MAX_VALUE);
Button goButton = new Button("Refresh");
goButton.setDefaultButton(true);
EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
eng.reload();
}
};
goButton.setOnAction(goAction);
GridPane grid = new GridPane();
grid.setVgap(0);
grid.setHgap(0);
GridPane.setConstraints(goButton,2,0,2,1, HPos.RIGHT, VPos.BOTTOM, Priority.ALWAYS, Priority.ALWAYS);
GridPane.setConstraints(view, 0, 0, 2, 1, HPos.CENTER, VPos.CENTER, Priority.SOMETIMES, Priority.SOMETIMES);
grid.getColumnConstraints().addAll(
new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true),
new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true)
);
grid.getChildren().addAll(goButton, view);
getChildren().add(grid);
}
#Override protected void layoutChildren() {
List<Node> managed = getManagedChildren();
double width = getWidth();
double height = getHeight();
double top = getInsets().getTop();
double right = getInsets().getRight();
double left = getInsets().getLeft();
double bottom = getInsets().getBottom();
for (int i = 0; i < managed.size(); i++) {
Node child = managed.get(i);
layoutInArea(child, left, top,
width - left - right, height - top - bottom,
0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
}
}
}
}
If you want to stack one component on top of another, don't use a GridPane for layout, instead use a parent that allows layout components to be placed on top of one another. For example, a standard Pane, a StackPane, Group or Region. In these stacked style layouts, the components are rendered in order of the child component's position in the parent's child list.
In your sample code you are already extending Pane, so get rid of all of the grid code and just do:
getChildren().addAll(view, goButton);
instead of:
grid.getChildren().addAll(goButton, view);
Modify the layout properties of your goButton to position it within a parent which does not manage the layout position of it's children, e.g. you can call goButton.relocate(xPos, yPos).
You have some custom stuff in the layoutChildren method you override that may mess up the default Pane layout processing logic. Overriding layoutChildren is more of an advanced layout topic and I wouldn't advise it for beginners.
Here is an updated sample you could look at which uses some of the concepts mentioned in this answer.
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class WebViewBrowser extends Application {
#Override public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new WebViewPane("http://google.com")));
stage.setFullScreen(true);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
class WebViewPane extends Pane {
final WebView view = new WebView();
final Button goButton = createGoButton(view.getEngine());
public WebViewPane(String initURL) {
view.getEngine().load(initURL);
getChildren().addAll(
view,
goButton
);
initLayout();
}
private Button createGoButton(final WebEngine eng) {
Button go = new Button("Refresh");
go.setDefaultButton(true);
go.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
eng.reload();
}
});
return go;
}
private void initLayout() {
setMinSize(500, 400);
setPrefSize(1024, 768);
view.prefWidthProperty().bind(widthProperty());
view.prefHeightProperty().bind(heightProperty());
goButton.setLayoutX(10);
goButton.layoutYProperty().bind(
heightProperty().subtract(20).subtract(goButton.heightProperty())
);
}
}