libgdx buttons not clickable - button

I have a problem with my current libGDX project.
The game starts with a main menu, where you can click on two buttons. After starting the game, you can pause it through Esc and get to the pause screen, which is very similar to the main menu.
I don't know why, but the buttons in the pause screen are not clickable.
Here is the code of the game screen with the problem:
public class GameScreen implements Screen{
private Texture[] monsterTextures = {Assets.manager.get(("Ressources/DemonHunter.jpg"), Texture.class), Assets.manager.get(("Ressources/WingedDemon.jpg"), Texture.class),
Assets.manager.get(("Ressources/Viking.jpg"), Texture.class), Assets.manager.get(("Ressources/DemonWarrior.jpg"), Texture.class)};
private Image[] monsterImages = {new Image(monsterTextures[0]), new Image(monsterTextures[1]), new Image(monsterTextures[2]), new Image(monsterTextures[3])};
private Stage gameStage = new Stage(), pauseStage = new Stage();
private Table table = new Table();
private Skin menuSkin = Assets.menuSkin;
private TextButton buttonContinue = new TextButton("Continue", menuSkin),
buttonExit = new TextButton("Exit", menuSkin);
private Label title = new Label ("Game", menuSkin);
private int randomMonster;
private int currentMonsterLife = 1 + (int)(Math.random() * ((5-1) + 1));
public static final int GAME_CREATING = 0;
public static final int GAME_RUNNING = 1;
public static final int GAME_PAUSED = 2;
private int gamestatus = 0;
#Override
public void show() {
randomMonster = 0 + (int)(Math.random() * ((3-0) + 1));
gameStage.addActor(monsterImages[randomMonster]);
}
public void newMonster() {
monsterImages[randomMonster].remove();
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
randomMonster = 0 + (int)(Math.random() * ((3-0) + 1));
currentMonsterLife = 1 + (int)(Math.random() * ((5-1) + 1));
gameStage.addActor(monsterImages[randomMonster]);
}
#Override
public void render(float delta) {
if(Gdx.input.isKeyJustPressed(Keys.ESCAPE)) pauseGame();
if(gamestatus == GAME_CREATING) {
buttonContinue.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y) {
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gamestatus = GAME_RUNNING;
}
});
buttonExit.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y) {
Gdx.app.exit();
}
});
table.add(title).padBottom(40).row();
table.add(buttonContinue).size(150, 60).padBottom(20).row();
table.add(buttonExit).size(150, 60).padBottom(20).row();
table.setFillParent(true);
pauseStage.addActor(table);
Gdx.input.setInputProcessor(pauseStage);
Gdx.input.setInputProcessor(gameStage);
gamestatus = GAME_RUNNING;
}
if(gamestatus == GAME_RUNNING) {
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gameStage.act();
gameStage.draw();
if(Gdx.input.justTouched())currentMonsterLife -= 1;
if(currentMonsterLife == 0)newMonster();
}
if(gamestatus == GAME_PAUSED) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
pauseStage.act();
pauseStage.draw();
}
}
public void pauseGame() {
gamestatus = GAME_PAUSED;
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void pause() {
pauseGame();
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
for(int i = 0; i < monsterTextures.length; i++) {
monsterTextures[i].dispose();
}
gameStage.dispose();
pauseStage.dispose();
menuSkin.dispose();
}
}
And here is the code of the main menu, where the buttons are working:
public class MainMenu implements Screen {
private Stage stage = new Stage();
private Table table = new Table();
private Skin menuSkin = Assets.menuSkin;
private TextButton buttonPlay = new TextButton("Play", menuSkin),
buttonExit = new TextButton("Exit", menuSkin);
private Label title = new Label ("Hunt for Power", menuSkin);
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
#Override
public void show() {
buttonPlay.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y) {
((Game)Gdx.app.getApplicationListener()).setScreen(new GameScreen());
}
});
buttonExit.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y) {
Gdx.app.exit();
}
});
table.add(title).padBottom(40).row();
table.add(buttonPlay).size(150, 60).padBottom(20).row();
table.add(buttonExit).size(150, 60).padBottom(20).row();
table.setFillParent(true);
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
stage.dispose();
}
}
I really hope someone is able to find the solution to this.
Greetings, Joshflux

There is something weird with how you set the InputProcessor:
in the show() method you set the Stage stage as the InputProcessor:
Gdx.input.setInputProcessor(stage);
so far so good, but in the render() method you set it to different stages than the one where your buttons are!
Gdx.input.setInputProcessor(pauseStage);
Gdx.input.setInputProcessor(gameStage);
==> remove this code from the render method! Also you should not have the other code that looks like it should only be executed when creating the screen inside the render() method. It seems like your code results in overlapping stages, buttons & tables and it is unclear which stage currently is set as InputProcessor.

Like #donfuxx said, you should not set your input processor in the render() method, but rather in show().
And you can only set one input processor at a time. Your second call to setInputProcessor replaces the first call. If you want two different stages as input processors, you must combine them with an InputMultiplexer:
public void show(){
Gdx.input.setInputProcessor(new InputMultiplexer(pauseStage, gameStage)); //list them in order of precedence
//...your other code
}

Related

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException while adding cloned object to Pane

I have the following class in which I am trying to implement the prototype pattern:
public class Element extends Group implements Cloneable{
private final double ELEMENT_WIDTH = 50;
private final double ELEMENT_HEIGHT = 70;
private final double CIRCLE_RADIUS = 1;
private int minimalNumberOfInputs;
private Shape body = new Rectangle(ELEMENT_WIDTH, ELEMENT_HEIGHT, Color.WHITE);
private Circle output = new Circle(CIRCLE_RADIUS);
private Line outputLine = new Line(ELEMENT_WIDTH, ELEMENT_HEIGHT / 2, ELEMENT_WIDTH + 15, ELEMENT_HEIGHT / 2);
private ArrayList<Circle> inputs;
private ArrayList<Line> inputLines;
private Circle inversionDesignation;
private Text symbol;
private Integer identifier;
private double bodyCorX;
private double bodyCorY;
private double corX = 0;
private double corY = 0;
private double mouseX = 0;
private double mouseY = 0;
private boolean dragging = false;
public Integer getIdentifier() {
return identifier;
}
public ArrayList<Circle> getInputs() {
return inputs;
}
public Circle getOutput() {
return output;
}
public Circle getInversionDesignation() {
return inversionDesignation;
}
public double getELEMENT_WIDTH() {
return ELEMENT_WIDTH;
}
public double getELEMENT_HEIGHT() {
return ELEMENT_HEIGHT;
}
public double getCIRCLE_RADIUS() {
return CIRCLE_RADIUS;
}
public int getMinimalNumberOfInputs() {
return minimalNumberOfInputs;
}
public Shape getBody() {
return body;
}
public Line getOutputLine() {
return outputLine;
}
public ArrayList<Line> getInputLines() {
return inputLines;
}
public Text getSymbol() {
return symbol;
}
public double getBodyCorX() {
return bodyCorX;
}
public double getBodyCorY() {
return bodyCorY;
}
public double getCorX() {
return corX;
}
public double getCorY() {
return corY;
}
public double getMouseX() {
return mouseX;
}
public double getMouseY() {
return mouseY;
}
public boolean isDragging() {
return dragging;
}
public Element(){
}
public Element(Circle inversionDesignation, Text symbol, int minimalNumberOfInputs) {
this.minimalNumberOfInputs = minimalNumberOfInputs;
this.body.setStroke(Color.BLACK);
this.body.setStrokeType(StrokeType.INSIDE);
this.body.setStrokeWidth(2.5);
this.output.setFill(Color.BLACK);
this.output.toFront();
this.inversionDesignation = inversionDesignation;
this.symbol = symbol;
this.inputs = new ArrayList<>();
this.inputLines = new ArrayList<>();
this.identifier = this.hashCode();
this.outputLine.setStrokeWidth(2);
this.createStartInputs();
this.configureInputPoints();
this.bindGraphicalElements();
elementMovementEvents();
elementEnteredEvents();
}
private void bindGraphicalElements() {
this.getChildren().add(body);
this.getChildren().add(output);
this.getChildren().add(outputLine);
this.getChildren().addAll(inputs);
this.getChildren().addAll(inputLines);
if (this.symbol != null) {
this.getChildren().add(symbol);
symbol.relocate((ELEMENT_WIDTH / 2) - symbol.getTabSize() / 2, ELEMENT_HEIGHT / 8);
symbol.setFont(new Font("Consolas", 14));
}
if (this.inversionDesignation != null) {
this.getChildren().add(inversionDesignation);
this.inversionDesignation.setStrokeType(StrokeType.INSIDE);
this.inversionDesignation.setStrokeWidth(1);
this.inversionDesignation.setStroke(Color.BLACK);
this.inversionDesignation.relocate((this.bodyCorX + this.ELEMENT_WIDTH) - (this.inversionDesignation.getRadius() + 1), (this.bodyCorY + this.ELEMENT_HEIGHT / 2) - this.inversionDesignation.getRadius());
inversionDesignation.toFront();
}
}
private void addGraphicalElement(Shape shape) {
this.getChildren().add(shape);
}
private void createStartInputs() {
for (int i = 0; i < this.minimalNumberOfInputs; i++) {
inputs.add(new Circle(CIRCLE_RADIUS));
inputs.get(i).setFill(Color.BLACK);
inputs.get(i).toFront();
}
configureInputPoints();
for (int i = 0; i < inputs.size(); i++) {
Line line = new Line(inputs.get(i).getLayoutX() - 15, inputs.get(i).getLayoutY(), inputs.get(i).getLayoutX(), inputs.get(i).getLayoutY());
line.setStrokeWidth(2);
inputLines.add(line);
}
}
private void addNewInput() {
Circle newCircle = new Circle(CIRCLE_RADIUS);
newCircle.setFill(Color.BLACK);
this.inputs.add(newCircle);
this.configureInputPoints();
this.addGraphicalElement(newCircle);
}
private void configureInputPoints() {
this.output.relocate((this.bodyCorX + this.ELEMENT_WIDTH) - (output.getRadius() + 1), (this.bodyCorY + this.ELEMENT_HEIGHT / 2) - output.getRadius());
int distance = (int) ELEMENT_HEIGHT / (inputs.size() + 1); //Растояние между точками входа.
for (int i = 0; i < inputs.size(); i++) {
inputs.get(i).relocate(this.bodyCorX - (CIRCLE_RADIUS - 1), this.bodyCorY + (distance * (i + 1) - CIRCLE_RADIUS));
}
}
private void elementMovementEvents() {
onMousePressedProperty().set(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
mouseX = event.getSceneX();
mouseY = event.getSceneY();
corX = getLayoutX();
corY = getLayoutY();
}
});
onMouseDraggedProperty().set(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
double offsetX = event.getSceneX() - mouseX; //смещение по X
double offsetY = event.getSceneY() - mouseY;
corX += offsetX;
corY += offsetY;
double scaledX = corX;
double scaledY = corY;
setLayoutX(scaledX);
setLayoutY(scaledY);
dragging = true;
mouseX = event.getSceneX();
mouseY = event.getSceneY();
event.consume();
}
});
onMouseClickedProperty().set(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
dragging = false;
}
});
}
private void testEvent() {
this.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
this.addNewInput();
});
}
private void elementEnteredEvents() {
onMouseClickedProperty().set(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getTarget() instanceof Circle) {
System.out.println("Circle!");
}
}
});
}
#Override
public Element clone() throws CloneNotSupportedException{
return (Element)super.clone();
}
#Override
public String toString() {
return "Element " + this.hashCode() + ": location = " + this.getLayoutX() + ": output = " + this.minimalNumberOfInputs;
}
#Override
public boolean equals(Object obj) {
if(!(obj instanceof Element)) return false;
Element element = (Element) obj;
return element.getBodyCorX() == bodyCorX && element.getBodyCorY() == bodyCorY && element.getBody() == body;
}
}
I am trying to implement a pattern using the following method:
#Override
public Element clone() throws CloneNotSupportedException{
return (Element)super.clone();
}
I have a controller like this:
public class FXMLController {
#FXML
private AnchorPane anchorPane;
#FXML
private AnchorPane workPane;
//prototypes
private Element AndPrototype = new Element(null, new Text("&"), 2);
private Element OrPrototype = new Element(null, new Text("1"), 2);
private Element NotPrototype = new Element(new Circle(5, Color.WHITE), null, 1);
private Element AndNotPrototype = new Element(new Circle(5, Color.WHITE), new Text("&"), 2);
private Element OrNotPrototype = new Element(new Circle(5, Color.WHITE), new Text("1"), 2);
#FXML
public void initialize() {
}
#FXML
private void method() throws CloneNotSupportedException {
workPane.getChildren().add(AndPrototype.clone());
}
}
In this method, I am trying to make a clone and add it to the AnchorPane
#FXML
private void method() throws CloneNotSupportedException {
workPane.getChildren().add(AndPrototype.clone());
}
As a result, when I click on the button, I get an error of the following content:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 8
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at javafx.base/com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.get(VetoableListDecorator.java:305)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1704)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1648)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1501)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:115)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:84)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:115)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3847)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3809)
at javafx.graphics/javafx.scene.Node.doComputeLayoutBounds(Node.java:3657)
at javafx.graphics/javafx.scene.Node$1.doComputeLayoutBounds(Node.java:449)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeLayoutBoundsImpl(NodeHelper.java:166)
at javafx.graphics/com.sun.javafx.scene.GroupHelper.computeLayoutBoundsImpl(GroupHelper.java:63)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeLayoutBounds(NodeHelper.java:106)
at javafx.graphics/javafx.scene.Node$13.computeBounds(Node.java:3509)
at javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9782)
at javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9752)
at javafx.graphics/javafx.scene.Node.getLayoutBounds(Node.java:3524)
at javafx.graphics/javafx.scene.layout.AnchorPane.computeWidth(AnchorPane.java:272)
at javafx.graphics/javafx.scene.layout.AnchorPane.computeMinWidth(AnchorPane.java:248)
at javafx.graphics/javafx.scene.Parent.minWidth(Parent.java:1048)
at javafx.graphics/javafx.scene.layout.Region.minWidth(Region.java:1553)
at javafx.graphics/javafx.scene.layout.Region.computeChildPrefAreaWidth(Region.java:2012)
at javafx.graphics/javafx.scene.layout.AnchorPane.computeChildWidth(AnchorPane.java:315)
at javafx.graphics/javafx.scene.layout.AnchorPane.layoutChildren(AnchorPane.java:353)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1207)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2476)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:413)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:412)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:439)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:831)
I have absolutely no idea what this error may be connected with and in which direction they are moving.
Usually this is caused because you modified the scene graph or an attribute of a scene graph node off of the JavaFX thread.
Similar stack traces all caused by threading errors:
javafx vlcj play mutiple video get IndexOutOfBoundsException error
Exception on JavaFX when moving Labels around their container.(IndexOutOfBoundsException)
How to fix IndexOutOfBounds exception when javafx recomputes Parent/Node Bounds
How do I find out what's causing this Java FX Application Thread exception?
If it is a multi-threading issue, usually it can be fixed by either removing unnecessary threading. Or if multi-threading is unavoidable, using tools like the javafx.concurrent package or Platform.runLater to ensure nodes in the active scene graph are only modified on the JavaFX thread.
However, if you don’t have any multi-threading going on, it might be down to the weird cloning stuff you have going on which may be ill-advised. JavaFX nodes can only occur once in the scene and the clones may cause glitches in the framework.

How to refresh pane in javafx

I recently have been learning JavaFX and have an issue about how to refresh the pane. In this simple program, I want the black square to move to the right into the next block when I am clicking the move button, but it doesn't work, I'm wondering how can I fix my code.
screen shot
Main Class:
public class Main extends Application {
private Cell cells[] = new Cell[5];
private Player player;
private Board board;
Button move = new Button("move");
public Main() throws Exception {
for (int i = 0; i < cells.length; i++) {
cells[i] = new Cell(i);
}
this.player = new Player(0, cells);
this.board = new Board(player, cells);
}
#Override
public void start(Stage primaryStage) throws Exception {
Main game = new Main();
BorderPane pane = new BorderPane();
pane.setCenter(board);
pane.setBottom(move);
Scene scene = new Scene(pane,400,80);
primaryStage.setTitle("Move");
primaryStage.setScene(scene);
primaryStage.show();
move.setOnAction(e -> game.move());
}
public void move() {
player.currentCell.index += 1;
board.paint();
}
public static void main(String[] args) {
launch(args);
}
}
Board class:
class Board extends Pane {
private Player player;
public Cell cells[];
private final int CELLWIDTH = 40;
private final int CELLHEIGHT = 40;
private final int LMARGIN = 100;
public Board(Player p, Cell cells[]) {
player = p;
this.cells = cells;
paint();
}
public void paint() {
Cell cell;
for (int i=0; i<cells.length; i++) {
cell = cells[i];
Rectangle r1 = new Rectangle(xCor(cell.index), 0, CELLWIDTH, CELLHEIGHT);
r1.setStroke(Color.BLACK);
r1.setFill(Color.WHITE);
getChildren().add(r1);
}
cell = player.currentCell;
Rectangle r2 = new Rectangle(xCor(cell.index), 0, CELLWIDTH, CELLHEIGHT);
r2.setFill(Color.BLACK);
getChildren().add(r2);
}
private int xCor(int col) {
return LMARGIN + col * CELLWIDTH;
}
}
Player Class:
class Player {
public int position;
public Cell currentCell;
public Player(int position, Cell cell[]) throws Exception {
this.currentCell = cell[0];
}
}
Cell Class:
class Cell {
public int index;
public Cell(int index) {
this.index = index;
}
}
You might want to reword your code, storing the player's location just in the Player class is going to make life difficult. I would also suggest adding a flag to the Cell class stating if the player is inside, e.g.
class Cell {
public int index;
private Player playerInCell;
public Cell(int index) {
this.index = index;
}
public void setPlayerInCell(Player p){
this.playerInCell = p;
}
public void clearPlayerInCell(){
this.playerInCell = null;
}
public Player getPlayerInCell(){
return this.playerInCell;
}
}
Then, upon moving a player to the Cell you can clear them from the previous Celland set them in the new one and in your Paint() function, if player is present, colour the cell in.
The other thing, if you wish to stick with your method, your issue is caused by that you are only changing the index property on the Cell class, you should also be either changing the Cell's position in the array cells[] or just changing the currentCell property of the Player class, otherwise your player always stays in the same place. Here is an example of changing the Player's currentCell property:
public void move() {
Cell currentCell = player.currentCell;
Cell nextCell = null;
for (int i = 0; i < cells.length; i++) {
if (cells[i] == currentCell && i+1 < cells.length){
nextCell = cells[i+1];
break;
}
}
if (nextCell != null)
player.currentCell = nextCell;
else{
//Error handling, next cell not found
}
board.paint();
}
[Edit]
I've done some major code cleanup, some of the ways you were doing things was a bit odd, I hope you don't mind, here are the classes that changed:
Main
public class Main extends Application {
private Cell cells[] = new Cell[5];
private Player player;
private Board board;
Button move = new Button("move");
public Main() throws Exception{
for (int i = 0; i < cells.length; i++) {
cells[i] = new Cell(i);
}
this.player = new Player(cells[0]);
this.board = new Board(player, cells);
}
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane pane = new BorderPane();
pane.setCenter(board);
pane.setBottom(move);
Scene scene = new Scene(pane,400,80);
primaryStage.setTitle("Move");
primaryStage.setScene(scene);
primaryStage.show();
move.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
move();
}
});
}
public void move() {
//Get current players cell, we want to move them one right
Cell currentCell = player.getCurrentCell();
Cell nextCell = null;
//Searching for current cell in board, if found we need to clear the player from it and select the next cell
for (int i = 0; i < cells.length; i++) {
if (cells[i] == currentCell && i+1 < cells.length){
cells[i].clearPlayerInCell();
nextCell = cells[i+1];
break;
}
}
//We found it, let's move the player
if (nextCell != null) {
player.setCurrentCell(nextCell);
nextCell.setPlayerInCell(player);
}
//We didn't find it, or our index was out of range, what do we do now?
else{
//Error handling, next cell not found
//Example, let's put them back at the start
player.setCurrentCell(cells[0]);
cells[0].setPlayerInCell(player);
cells[cells.length-1].clearPlayerInCell();
}
board.paint();
}
public static void main(String[] args) {
launch(args);
}
}
Board
public class Board extends Pane {
private Player player;
private Cell cells[];
private final int CELLWIDTH = 40;
private final int CELLHEIGHT = 40;
private final int LMARGIN = 100;
public Board(Player p, Cell cells[]) {
player = p;
this.cells = cells;
paint();
}
public Cell[] getCells(){
return this.cells;
}
public Player getPlayer() {
return player;
}
public void paint() {
//Clear previous cells, we don't need them now
getChildren().clear();
//Redraw them
for(Cell cell : cells){
Rectangle r1 = new Rectangle(xCor(cell.getIndex()), 0, CELLWIDTH, CELLHEIGHT);
r1.setStroke(Color.BLACK);
//We've found a player in the cell, let's colour it black
if (cell.getPlayerInCell() != null)
r1.setFill(Color.BLACK);
//No, player in this cell, white it is
else
r1.setFill(Color.WHITE);
getChildren().add(r1);
}
}
private int xCor(int col) {
return LMARGIN + col * CELLWIDTH;
}
}
Player
public class Player {
private Cell currentCell;
public Player(Cell cell) throws Exception {
this.currentCell = cell;
cell.setPlayerInCell(this);
}
public Cell getCurrentCell(){
return this.currentCell;
}
public void setCurrentCell(Cell cell){
this.currentCell = cell;
}
}
Cell
public class Cell {
private int index;
private Player playerInCell;
public Cell(int index) {
this.index = index;
}
public void setPlayerInCell(Player p){
this.playerInCell = p;
}
public void clearPlayerInCell(){
this.playerInCell = null;
}
public Player getPlayerInCell(){
return this.playerInCell;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
That now works and I can move the cell along, I've also set it so that the cell goes back to the beginning if the player reaches the end, but that's an example.
It works off using the Cell property of playerInCell, if that isn't null then we know a player is in the cell and can colour it black. If it is null, no player is in the cell and we can colour it white. This also allows you in the future to maybe have more players with different colours. Though I don't know what your end goal is. Hope this helps and if you want any further explanation, feel free to ask
Also, for further reading, see here why it's better to use getter and setters like I have
Also, the reasoning behind this bit of code:
move.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
move();
}
});
Is because I'm using Java 1.7 instead of Java 1.8 and can't use predicates, you should be safe to change that to move.setOnAction(e -> this.move()); instead.

JavaFx unable to execute javascript function

I am using JavaFX to embed browser. I am trying to run a javascript function addnum() from java class WebScale, but i am getting error.If i execute document.write() from webengine.executeScript() it is possible. But i cant call my function.
My code is as follow:
public class WebScale extends JApplet {
static ZoomingPane zoomingPane;
private static JFXPanel fxContainer;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame("Area Configurator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new WebScale();
applet.init();
frame.setContentPane(applet.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
applet.start();
frame.addComponentListener(new java.awt.event.ComponentAdapter() {
#Override
public void componentResized(java.awt.event.ComponentEvent evt) {
if (zoomingPane != null) {
zoomingPane.setZoomFactors((double)(frame.getWidth()/ 1280.0), (double)(frame.getHeight() / 800.0));
}
}
});
}
});
}
#Override
public void init() {
fxContainer = new JFXPanel();
fxContainer.setPreferredSize(new Dimension(800, 700));
add(fxContainer, BorderLayout.CENTER);
// create JavaFX scene
Platform.runLater(new Runnable() {
#Override
public void run() {
createScene();
}
});
}
private void createScene() {
WebView webView = new WebView();
zoomingPane = new ZoomingPane(webView);
BorderPane bp = new BorderPane();
bp.setCenter(zoomingPane);
fxContainer.setScene(new Scene(bp));
String strpath ;
strpath="file:///C:/Users/Priyanka/Desktop/FDASH/StationV3/Main.html";
final WebEngine engine = webView.getEngine();
engine.load(strpath);
engine.executeScript("addNum()");
}
private class ZoomingPane extends Pane {
Node content;
private final DoubleProperty zoomFactor = new SimpleDoubleProperty(1);
private double zoomFactory = 1.0;
private ZoomingPane(Node content) {
this.content = content;
getChildren().add(content);
final Scale scale = new Scale(1, 1);
content.getTransforms().add(scale);
zoomFactor.addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
scale.setX(newValue.doubleValue());
scale.setY(zoomFactory);
requestLayout();
}
});
}
#Override
protected void layoutChildren() {
Pos pos = Pos.TOP_LEFT;
double width = getWidth();
double height = getHeight();
double top = getInsets().getTop();
double right = getInsets().getRight();
double left = getInsets().getLeft();
double bottom = getInsets().getBottom();
double contentWidth = (width - left - right)/zoomFactor.get();
double contentHeight = (height - top - bottom)/zoomFactory;
layoutInArea(content, left, top,
contentWidth, contentHeight,
0, null,
pos.getHpos(),
pos.getVpos());
}
public final Double getZoomFactor() {
return zoomFactor.get();
}
public final void setZoomFactor(Double zoomFactor) {
this.zoomFactor.set(zoomFactor);
}
public final void setZoomFactors(Double zoomFactorx, Double Zoomfactory) {
this.zoomFactory = Zoomfactory;
this.zoomFactor.set(zoomFactorx);
}
public final DoubleProperty zoomFactorProperty() {
return zoomFactor;
}
}
}
I am getting the following error.
Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: ReferenceError: Can't find variable: addNum
at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:128)
at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
at com.sun.webkit.WebPage.executeScript(WebPage.java:1439)
at javafx.scene.web.WebEngine.executeScript(WebEngine.java:982)
at c.WebScale.createScene(WebScale.java:97)
at c.WebScale.access$0(WebScale.java:83)
at c.WebScale$2.run(WebScale.java:78)
at com.sun.javafx.application.PlatformImpl.lambda$null$174(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$175(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
Assuming addNum() is defined in Main.html, the javascript hasn't been loaded at the time that you're calling it. You should add a listener so you can call your javascript once the page is fully loaded:
final WebEngine engine = webView.getEngine();
engine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
engine.executeScript("addNum()");
}
}
});
engine.load(strpath);

Trying to implement swipe movement

public class CoursesActivity extends SherlockFragmentActivity {
ArrayList<CourseData> mCoursesList = new ArrayList<CourseData>();
public CoursesListAdapter coursesListAdapter;
public ListView mList;
public AlertDialog.Builder dlgAlert;
public Dialog loginDialog;
public Dialog loginDialogOverflow;
LinearLayout progressBar;
static SQLiteWebcourse dbHelper;
private GestureDetectorCompat mDetector;
public final static String EXTRA_MESSAGE = "com.technion.coolie.webcourse.MESSAGE";
public CoursesActivity() {
dbHelper = new SQLiteWebcourse(this, "WebcoureDB", null, 1);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create list of courses
mCoursesList = new ArrayList<CourseData>();
setContentView(R.layout.web_activity_courses);
mList = (ListView) findViewById(R.id.courses_list);
dlgAlert = new AlertDialog.Builder(getApplicationContext());
if (!CoolieAccount.WEBCOURSE.isAlreadyLoggedIn()) {
loginDialog = CoolieAccount.WEBCOURSE.openSigninDialog(this);
OnDismissListener dismissListener = new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// Check if connection success
if (CoolieAccount.WEBCOURSE.isAlreadyLoggedIn()) {
// Connection SUCCESS
progressBar = (LinearLayout) findViewById(R.id.progressBarLayout_courses);
progressBar.setVisibility(View.VISIBLE);
asyncParse<CourseData> a = new asyncParse<CourseData>() {
#Override
protected List<CourseData> doInBackground(
String... params) {
// TODO Auto-generated method stub
try {
courseList crL = new courseList(
getApplicationContext());
crL.getCourses(CoolieAccount.WEBCOURSE
.getUsername(),
CoolieAccount.WEBCOURSE
.getPassword());
mCoursesList = dbHelper
.getAllCourses(CoolieAccount.WEBCOURSE
.getUsername());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doInBackground(params);
}
#Override
protected void onPostExecute(List<CourseData> result) {
// TODO Auto-generated method stub
CoursesListAdapter coursesListAdapter = new CoursesListAdapter(
getApplicationContext(), mCoursesList);
mList.setAdapter(coursesListAdapter);
mList.setBackgroundColor(0xFFF0F0F0);
progressBar.setVisibility(View.INVISIBLE);
super.onPostExecute(result);
}
};
a.execute("");
} else {
// Connection FAILED
Log.v("dbAss", "Second Time");
}
}
};
loginDialog.setOnDismissListener(dismissListener);
} else {
mCoursesList = dbHelper.getAllCourses(CoolieAccount.WEBCOURSE
.getUsername());
CoursesListAdapter coursesListAdapter = new CoursesListAdapter(
getApplicationContext(), mCoursesList);
mList.setAdapter(coursesListAdapter);
mList.setBackgroundColor(0xFFF0F0F0);
}
Log.v("Gestures", "OnTouchEvent#!$#%##%^&^$%");
// OnItemClickListener itemClicked = new OnItemClickListener() {
//
// #Override
// public void onItemClick(AdapterView<?> list, View view,
// int position, long id) {
// // TODO Auto-generated method stub
// loadCourseInformationActivity(((CourseData) mList
// .getItemAtPosition(position)).CourseDescription);
// }
// };
// mList.setOnItemClickListener(itemClicked);
mDetector = new GestureDetectorCompat(this, new MyGestureListener());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("Gestures", "OnTouchEvent#!$#%##%^&^$%");
this.mDetector.onTouchEvent(event);
// Be sure to call the superclass implementation
return super.onTouchEvent(event);
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
private static final String DEBUG_TAG = "Gestures";
#Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.v(DEBUG_TAG,
"onFling: " + event1.toString() + event2.toString());
Toast.makeText(getApplicationContext(), "SWIPED", Toast.LENGTH_LONG)
.show();
if (event2.getX() - event1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY)
Toast.makeText(getApplicationContext(), "SWIPED",
Toast.LENGTH_LONG).show();
// if (showDeleteButton(e1))
// return true;
return super.onFling(event1, event2, velocityX, velocityY);
}
}
}
Hey fellas, i'm trying to implement swipe detection I went through android lesson and did exactly what is written there: http://developer.android.com/training/gestures/detector.html
For some reason when I touch the screen it doesnt go to onTouchEvent. What seems to be the problem?
You haven't set the touch listener to your ListView.
listView.setOnTouchListener(this);

Image in button - j2me

I am trying to build a simple menu-based GUI with J2ME. The menu entries are currently objects of classes derived from the class Button. Is there any way I can:
Replace the text in the button and have an image show instead, sort of an icon?
Make the text and image appear side by side on the same menu bar.
If my question is not clear, please let me know and I will edit it.
You can create your own Item that looks like a button by extending the CustomItem class.
This is a working MIDlet with a good MyButton class:
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.CustomItem;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.midlet.MIDlet;
public class TestMidlet extends MIDlet implements ItemStateListener {
class MyButton extends CustomItem {
private Image _image = null;
private boolean _down = false;
private int _clicks = 0;
public MyButton(Image image) {
super("");
_image = image;
}
// Button's image
public void setImage(Image image) {
_image = image;
repaint();
}
public Image getImage() {
return _image;
}
// Has the button been clicked?
public boolean isClicked() {
if(_clicks>0) {
_clicks -= 1;
return true;
}
return false;
}
// Is the button currently down?
public boolean isDown() {
return _down;
}
public void setDown(boolean down) {
if(_down)
_clicks += 1;
if(down!=_down) {
_down = down;
repaint();
notifyStateChanged();
}
}
public void setDown() {
setDown(true);
}
public void setUp() {
setDown(false);
}
// Minimal button size = image size
protected int getMinContentHeight() {
return getImage().getHeight();
}
protected int getMinContentWidth() {
return getImage().getWidth();
}
// Preferred button size = image size + borders
protected int getPrefContentHeight(int width) {
return getImage().getHeight()+2;
}
protected int getPrefContentWidth(int height) {
return getImage().getWidth()+2;
}
// Button painting procedure
protected void paint(Graphics g, int w, int h) {
// Fill the button with grey color - background
g.setColor(192, 192, 192);
g.fillRect(0, 0, w, h);
// Draw the image in the center of the button
g.drawImage(getImage(), w/2, h/2, Graphics.HCENTER|Graphics.VCENTER);
// Draw the borders
g.setColor(isDown()?0x000000:0xffffff);
g.drawLine(0, 0, w, 0);
g.drawLine(0, 0, 0, h);
g.setColor(isDown()?0xffffff:0x000000);
g.drawLine(0, h-1, w, h-1);
g.drawLine(w-1, 0, w-1, h);
}
// If FIRE key is pressed, the button becomes pressed (down state)
protected void keyPressed(int c) {
if(getGameAction(c)==Canvas.FIRE)
setDown();
}
// When FIRE key is released, the button becomes released (up state)
protected void keyReleased(int c) {
if(getGameAction(c)==Canvas.FIRE)
setUp();
}
// The same for touchscreens
protected void pointerPressed(int x, int y) {
setDown();
}
protected void pointerReleased(int x, int y) {
setUp();
}
}
MyButton button = null;
public void itemStateChanged(Item item) {
if(item==button) {
if(button.isClicked())
System.out.print("clicked, ");
System.out.println(button.isDown()?"currently down":"currently up");
}
}
public void startApp() {
try {
Form form = new Form("Example");
button = new MyButton(Image.createImage("/icon.png"));
form.append(button);
form.setItemStateListener(this);
Display.getDisplay(this).setCurrent(form);
} catch(Exception e) {
e.printStackTrace();
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
notifyDestroyed();
}
}

Resources