I am trying to set node animation, that depends on previous animations of that node as well as other nodes.
To demonstrate the issue I'll use a simple Pane with 4 Label children:
The main class as well as the model and view classes:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.util.Duration;
public final class Puzzle extends Application{
private Controller controller;
#Override
public void start(Stage stage) throws Exception {
controller = new Controller();
BorderPane root = new BorderPane(controller.getBoardPane());
root.setTop(controller.getControlPane());
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch();}
}
class View{
private static final double size = 70;
private static Duration animationDuration = Duration.millis(600);
private int[][] cellModels;
private Node[][] cellNodes;
private CountDownLatch latch;
Button play = new Button("Play");
private Pane board, control = new HBox(play);;
View(Model model) {
cellModels = model.getCellModels();
cellNodes = new Node[cellModels.length][cellModels[0].length];
makeBoardPane();
((HBox) control).setAlignment(Pos.CENTER_RIGHT);
}
private void makeBoardPane() {
board = new Pane();
for (int row = 0; row < cellModels.length ; row ++ ) {
for (int col = 0; col < cellModels[row].length ; col ++ ) {
Label label = new Label(String.valueOf(cellModels[row][col]));
label.setPrefSize(size, size);
Point2D location = getLocationByRowCol(row, col);
label.setLayoutX(location.getX());
label.setLayoutY(location.getY());
label.setStyle("-fx-border-color:blue");
label.setAlignment(Pos.CENTER);
cellNodes[row][col] = label;
board.getChildren().add(label);
}
}
}
synchronized void updateCell(int id, int row, int column) {
if(latch !=null) {
try {
latch.await();
} catch (InterruptedException ex) { ex.printStackTrace();}
}
latch = new CountDownLatch(1);
Node node = getNodesById(id).get(0);
Point2D newLocation = getLocationByRowCol(row, column);
Point2D moveNodeTo = node.parentToLocal(newLocation );
TranslateTransition transition = new TranslateTransition(animationDuration, node);
transition.setFromX(0); transition.setFromY(0);
transition.setToX(moveNodeTo.getX());
transition.setToY(moveNodeTo.getY());
//set animated node layout to the translation co-ordinates:
//https://stackoverflow.com/a/30345420/3992939
transition.setOnFinished(ae -> {
node.setLayoutX(node.getLayoutX() + node.getTranslateX());
node.setLayoutY(node.getLayoutY() + node.getTranslateY());
node.setTranslateX(0);
node.setTranslateY(0);
latch.countDown();
});
transition.play();
}
private List<Node> getNodesById(int...ids) {
List<Node> nodes = new ArrayList<>();
for(Node node : board.getChildren()) {
if(!(node instanceof Label)) { continue; }
for(int id : ids) {
if(((Label)node).getText().equals(String.valueOf(id))) {
nodes.add(node);
break;
}
}
}
return nodes ;
}
private Point2D getLocationByRowCol(int row, int col) {
return new Point2D(size * col, size * row);
}
Pane getBoardPane() { return board; }
Pane getControlPane() { return control;}
Button getPlayBtn() {return play ;}
}
class Model{
private int[][] cellModels = new int[][] { {0,1}, {2,3} };
private SimpleObjectProperty<int[][]> cellModelsProperty =
cellModelsProperty = new SimpleObjectProperty<>(cellModels);
void addChangeListener(ChangeListener<int[][]> listener) {
cellModelsProperty.addListener(listener);
}
int[][] getCellModels() {
return (cellModelsProperty == null) ? null : cellModelsProperty.get();
}
void setCellModels(int[][] cellModels) {
cellModelsProperty.set(cellModels);
}
}
and the controller class:
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.layout.Pane;
class Controller {
private View view ;
private Model model;
Controller() {
model = new Model();
model.addChangeListener(getModelCangeListener());//observe model changes
view = new View(model);
view.getPlayBtn().setOnAction( a -> shuffle()); //animation works fine
//view.getPlayBtn().setOnAction( a -> IntStream.
// range(0,4).forEach( (i)-> shuffle())); //messes the animation
}
private ChangeListener<int[][]> getModelCangeListener() {
return (ObservableValue<? extends int[][]> observable,
int[][] oldValue, int[][] newValue)-> {
for (int row = 0; row < newValue.length ; row++) {
for (int col = 0; col < newValue[row].length ; col++) {
if(newValue[row][col] != oldValue[row][col]) {
final int fRow = row, fCol = col;
new Thread( () -> view.updateCell(
newValue[fRow][fCol], fRow, fCol)).start();
}
}
}
};
}
void shuffle() {
int[][] modelData = model.getCellModels();
int rows = modelData.length, columns = modelData[0].length;
int[][] newModelData = new int[rows][columns];
for (int row = 0; row < rows ; row ++) {
for (int col = 0; col < columns ; col ++) {
int colIndex = ((col+1) < columns ) ? col + 1 : 0;
int rowIndex = ((col+1) < columns ) ? row : ((row + 1) < rows) ? row +1 : 0;
newModelData[row][col] = modelData[rowIndex][colIndex];
}
}
model.setCellModels(newModelData);
}
Pane getBoardPane() { return view.getBoardPane(); }
Pane getControlPane() { return view.getControlPane(); }
}
Play button handler changes the model data (see shuffle()), the change triggers ChangeListener. The ChangeListener animates each changed label by invoking view.updateCell(..) on a separate thread. This all works as expected.
The problem starts when I try to run a few consecutive model updates (shuffle()). To simulate it I change
view.getPlayBtn().setOnAction( a -> shuffle());
with
view.getPlayBtn().setOnAction( a -> IntStream.range(0,4).forEach( (i)-> shuffle()));
which messes the animation (it plays in wrong order and ends up in wrong positions).
This does not come as a surprise: to work properly animations have to be played in a certain order: a label should be re-animated only after all four labels finished their previous animation.
The code posted runs each update on a thread, so execution order is not guaranteed.
My question is what is the right way to implement the needed sequence of multiple nodes and multiple animations ?
I looked at SequentialTransition but I couldn't figure out how it can be used to overcome the issue in question.
I did come up with a solution which I will post as an answer, because of the length of this post, and because I don't think the solution is good.
Your code does not adhere to the seperation of concerns principle. (Or at least you don't do it well.)
The animation should be done by the view and the view alone instead of collaborating between the controller and the view. Put all the animations for scheduling the animations in the View class.
SequentialTransition could wrap multiple animations in a single animation that plays them sequentially, but it shouldn't be the controller's concern to do this.
public class View {
private static final double SIZE = 70;
private static final Duration ANIMATION_DURATION = Duration.millis(600);
private final Map<Integer, Label> labelsById = new HashMap<>(); // stores labels by id
private final Button play = new Button("Play");
private Pane board;
private final HBox control;
private final Timeline animation;
private final LinkedList<ElementPosition> pendingAnimations = new LinkedList<>(); // stores parameter combination for update calls
private Node animatedNode;
public View(int[][] cellModels) { // we don't really need the whole model here
makeBoardPane(cellModels);
this.control = new HBox(play);
control.setAlignment(Pos.CENTER_RIGHT);
final DoubleProperty interpolatorValue = new SimpleDoubleProperty();
animation = new Timeline(
new KeyFrame(Duration.ZERO, evt -> {
ElementPosition ePos = pendingAnimations.removeFirst();
animatedNode = labelsById.get(ePos.id);
Point2D newLocation = getLocationByRowCol(ePos.row, ePos.column);
// create binding for layout pos
animatedNode.layoutXProperty().bind(
interpolatorValue.multiply(newLocation.getX() - animatedNode.getLayoutX())
.add(animatedNode.getLayoutX()));
animatedNode.layoutYProperty().bind(
interpolatorValue.multiply(newLocation.getY() - animatedNode.getLayoutY())
.add(animatedNode.getLayoutY()));
}, new KeyValue(interpolatorValue, 0d)),
new KeyFrame(ANIMATION_DURATION, evt -> {
interpolatorValue.set(1);
// remove bindings
animatedNode.layoutXProperty().unbind();
animatedNode.layoutYProperty().unbind();
animatedNode = null;
if (pendingAnimations.isEmpty()) {
// abort, if no more animations are pending
View.this.animation.stop();
}
}, new KeyValue(interpolatorValue, 1d)));
animation.setCycleCount(Animation.INDEFINITE);
}
private void makeBoardPane(int[][] cellModels) {
board = new Pane();
for (int row = 0; row < cellModels.length; row++) {
for (int col = 0; col < cellModels[row].length; col++) {
Point2D location = getLocationByRowCol(row, col);
int id = cellModels[row][col];
Label label = new Label(Integer.toString(id));
label.setPrefSize(SIZE, SIZE);
label.setLayoutX(location.getX());
label.setLayoutY(location.getY());
label.setStyle("-fx-border-color:blue");
label.setAlignment(Pos.CENTER);
labelsById.put(id, label);
board.getChildren().add(label);
}
}
}
private static class ElementPosition {
private final int id;
private final int row;
private final int column;
public ElementPosition(int id, int row, int column) {
this.id = id;
this.row = row;
this.column = column;
}
}
public void updateCell(int id, int row, int column) {
pendingAnimations.add(new ElementPosition(id, row, column));
animation.play();
}
private static Point2D getLocationByRowCol(int row, int col) {
return new Point2D(SIZE * col, SIZE * row);
}
public Pane getBoard() {
return board;
}
public Pane getControlPane() {
return control;
}
public Button getPlayBtn() {
return play;
}
}
Usage example with reduced complexity:
private int[][] oldValue;
#Override
public void start(Stage primaryStage) {
List<Integer> values = new ArrayList<>(Arrays.asList(0, 1, 2, 3));
oldValue = new int[][]{{0, 1}, {2, 3}};
View view = new View(oldValue);
Button btn = new Button("Shuffle");
btn.setOnAction((ActionEvent event) -> {
Collections.shuffle(values);
int[][] newValue = new int[2][2];
for (int i = 0; i < 2 * 2; i++) {
newValue[i / 2][i % 2] = values.get(i);
}
System.out.println(values);
for (int row = 0; row < newValue.length; row++) {
for (int col = 0; col < newValue[row].length; col++) {
if (newValue[row][col] != oldValue[row][col]) {
view.updateCell(newValue[row][col], row, col);
}
}
}
oldValue = newValue;
});
Scene scene = new Scene(new BorderPane(view.getBoard(), null, view.getControlPane(), btn, null));
primaryStage.setScene(scene);
primaryStage.show();
}
The solution I came up with involved controlling the execution order of the updating threads.
Todo it I changed the controller class by implementing an inner class based on this
so answer. See UpdateView in the following code.
I also modified getModelCangeListener() to use UpdateView:
import java.util.stream.IntStream;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.layout.Pane;
class Controller {
private View view ;
private Model model;
private static int threadNumber = 0, threadAllowedToRun = 0;
private static final Object myLock = new Object();
Controller() {
model = new Model();
model.addChangeListener(getModelCangeListener());//observe model changes
view = new View(model);
view.getPlayBtn().setOnAction( a -> IntStream.
range(0,4).forEach( (i)-> shuffle()));
}
private ChangeListener<int[][]> getModelCangeListener() {
return (ObservableValue<? extends int[][]> observable,
int[][] oldValue, int[][] newValue)-> {
for (int row = 0; row < newValue.length ; row++) {
for (int col = 0; col < newValue[row].length ; col++) {
if(newValue[row][col] != oldValue[row][col]) {
final int fRow = row, fCol = col;
new Thread( new UpdateView(
newValue[fRow][fCol], fRow, fCol)).start();
}
}
}
};
}
private void shuffle() {
int[][] modelData = model.getCellModels();
int rows = modelData.length, columns = modelData[0].length;
int[][] newModelData = new int[rows][columns];
for (int row = 0; row < rows ; row ++) {
for (int col = 0; col < columns ; col ++) {
int colIndex = ((col+1) < columns ) ? col + 1 : 0;
int rowIndex = ((col+1) < columns ) ? row : ((row + 1) < rows) ? row +1 : 0;
newModelData[row][col] = modelData[rowIndex][colIndex];
}
}
model.setCellModels(newModelData);
}
Pane getBoardPane() { return view.getBoardPane(); }
Pane getControlPane() { return view.getControlPane(); }
//https://stackoverflow.com/a/23097860/3992939
class UpdateView implements Runnable {
private int id, row, col, threadID;
UpdateView(int id, int row, int col) {
this.id = id; this.row = row; this.col = col;
threadID = threadNumber++;
}
#Override
public void run() {
synchronized (myLock) {
while (threadID != threadAllowedToRun) {
try {
myLock.wait();
} catch (InterruptedException e) {}
}
view.updateCell(id, row, col);
threadAllowedToRun++;
myLock.notifyAll();
}
}
}
}
While it as a possible solution I think a solution based on JavaFx own tools is preferable.
The following answer is based this answer. I refactored it, breaking it into smaller, more verbose "pieces", which makes it (for me) easier to understand.
I am posting it in hope it will help others as well.
import java.util.LinkedList;
import java.util.stream.IntStream;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.util.Duration;
public final class Puzzle extends Application{
private Controller controller;
#Override
public void start(Stage stage) throws Exception {
controller = new Controller();
BorderPane root = new BorderPane(controller.getBoardPane());
root.setTop(controller.getControlPane());
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch();}
}
class Controller {
private View view ;
private Model model;
Controller() {
model = new Model();
model.addChangeListener(getModelCangeListener());//observe model changes
view = new View(model);
view.getPlayBtn().setOnAction( a -> IntStream.
range(0,4).forEach( (i)-> shuffle()));
}
private ChangeListener<int[][]> getModelCangeListener() {
return (ObservableValue<? extends int[][]> observable,
int[][] oldValue, int[][] newValue)-> {
for (int row = 0; row < newValue.length ; row++) {
for (int col = 0; col < newValue[row].length ; col++) {
if(newValue[row][col] != oldValue[row][col]) {
view.updateCell(newValue[row][col], row, col);
}
}
}
};
}
private void shuffle() {
int[][] modelData = model.getCellModels();
int rows = modelData.length, columns = modelData[0].length;
int[][] newModelData = new int[rows][columns];
for (int row = 0; row < rows ; row ++) {
for (int col = 0; col < columns ; col ++) {
int colIndex = ((col+1) < columns ) ? col + 1 : 0;
int rowIndex = ((col+1) < columns ) ? row : ((row + 1) < rows) ? row +1 : 0;
newModelData[row][col] = modelData[rowIndex][colIndex];
}
}
model.setCellModels(newModelData);
}
Pane getBoardPane() { return view.getBoardPane(); }
Pane getControlPane() { return view.getControlPane(); }
}
class View{
private final Timeline timeLineAnimation;// private final Timeline timeLineAnimation;
private final LinkedList<ElementPosition> pendingAnimations = new LinkedList<>(); // stores parameter combination for update calls
private static final Duration ANIMATION_DURATION = Duration.millis(600);
private static final double SIZE = 70;
private int[][] cellModels;
private final Button play = new Button("Play");
private Pane board, control = new HBox(play);
Node animatedNode;
View(Model model) {
cellModels = model.getCellModels();
makeBoardPane();
((HBox) control).setAlignment(Pos.CENTER_RIGHT);
timeLineAnimation = new TimeLineAnimation().get();
}
private void makeBoardPane() {
board = new Pane();
for (int row = 0; row < cellModels.length ; row ++ ) {
for (int col = 0; col < cellModels[row].length ; col ++ ) {
int id = cellModels[row][col];
Label label = new Label(String.valueOf(id));
label.setPrefSize(SIZE, SIZE);
Point2D location = getLocationByRowCol(row, col);
label.setLayoutX(location.getX());
label.setLayoutY(location.getY());
label.setStyle("-fx-border-color:blue");
label.setAlignment(Pos.CENTER);
label.setId(String.valueOf(id));
board.getChildren().add(label);
}
}
}
public void updateCell(int id, int row, int column) {
pendingAnimations.add(new ElementPosition(id, row, column));
timeLineAnimation.play();
}
private Node getNodeById(int id) {
return board.getChildren().filtered(n ->
Integer.valueOf(n.getId()) == id).get(0);
}
private Point2D getLocationByRowCol(int row, int col) {
return new Point2D(SIZE * col, SIZE * row);
}
Pane getBoardPane() { return board; }
Pane getControlPane() { return control;}
Button getPlayBtn() {return play ;}
private static class ElementPosition {
private final int id, row, column;
public ElementPosition(int id, int row, int column) {
this.id = id;
this.row = row;
this.column = column;
}
}
class TimeLineAnimation {
private final Timeline timeLineAnimation;
//value to be interpolated by time line
final DoubleProperty interpolatorValue = new SimpleDoubleProperty();
private Node animatedNode;
TimeLineAnimation() {
timeLineAnimation = new Timeline(getSartKeyFrame(), getEndKeyFrame());
timeLineAnimation.setCycleCount(Animation.INDEFINITE);
}
// a 0 duration event, used to do the needed setup for next key frame
private KeyFrame getSartKeyFrame() {
//executed when key frame ends
EventHandler<ActionEvent> onFinished = evt -> {
//protects against "playing" when no pending animations
if(pendingAnimations.isEmpty()) {
timeLineAnimation.stop();
return;
};
ElementPosition ePos = pendingAnimations.removeFirst();
animatedNode = getNodeById(ePos.id);
Point2D newLocation = getLocationByRowCol(ePos.row, ePos.column);
// bind x,y layout properties interpolated property interpolation effects
//both x and y
animatedNode.layoutXProperty().bind(
interpolatorValue.multiply(newLocation.getX() - animatedNode.getLayoutX())
.add(animatedNode.getLayoutX()));
animatedNode.layoutYProperty().bind(
interpolatorValue.multiply(newLocation.getY() - animatedNode.getLayoutY())
.add(animatedNode.getLayoutY()));
};
KeyValue startKeyValue = new KeyValue(interpolatorValue, 0d);
return new KeyFrame(Duration.ZERO, onFinished, startKeyValue);
}
private KeyFrame getEndKeyFrame() {
//executed when key frame ends
EventHandler<ActionEvent> onFinished =evt -> {
// remove bindings
animatedNode.layoutXProperty().unbind();
animatedNode.layoutYProperty().unbind();
};
KeyValue endKeyValue = new KeyValue(interpolatorValue, 1d);
return new KeyFrame(ANIMATION_DURATION, onFinished, endKeyValue);
}
Timeline get() { return timeLineAnimation; }
}
}
class Model{
private int[][] cellModels = new int[][] { {0,1}, {2,3} };
private SimpleObjectProperty<int[][]> cellModelsProperty =
cellModelsProperty = new SimpleObjectProperty<>(cellModels);
void addChangeListener(ChangeListener<int[][]> listener) {
cellModelsProperty.addListener(listener);
}
int[][] getCellModels() {
return (cellModelsProperty == null) ? null : cellModelsProperty.get();
}
void setCellModels(int[][] cellModels) { cellModelsProperty.set(cellModels);}
}
(to run copy paste the entire code into Puzzle.java)
Related
I am currently trying to create a game with falling "asteroids" that a ship has to dodge. I have currently created a pane that is a large circle stacked with multiple smaller circles. Unfortunately, the pane's "hitbox" is a square/rectangle, rather than a circle, which is frustrating. The other alternate way of fixing this would be to create a circle and fill it with an image of an asteroid, but I couldn't find this anywhere. I know of:
circle.setFill(Color.WHATEVER);
but i would like for it to look like an asteroid, not just a simple grey circle falling. To sum it up, how can I set an image to a shape? Or, if there is a way to change the hitbox of a stackpane, a way to do that would also help fix my issue!
Any help is greatly appreciated! Thanks!
EDIT:
Below are the 4 files that will make a simplified version of my game work with the same problem:
DodgerRemake:
package javafxapplication6;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class DodgerRemake extends Application
{
private Spaceship thisSpaceShip = new Spaceship();
private BoxPane gamePane = new BoxPane(thisSpaceShip);
BorderPane pane = new BorderPane();
private BooleanProperty upPressed = new SimpleBooleanProperty();
private BooleanProperty rightPressed = new SimpleBooleanProperty();
private BooleanProperty downPressed = new SimpleBooleanProperty();
private BooleanProperty leftPressed = new SimpleBooleanProperty();
private BooleanBinding anyPressed = upPressed.or(rightPressed).or(downPressed).or(leftPressed);
protected BorderPane getPane()
{
StackPane centerPane = new StackPane();
centerPane.getChildren().add(gamePane);
pane.setCenter(centerPane);
Button thisButton = new Button("Start");
thisButton.setAlignment(Pos.CENTER);
thisButton.setFocusTraversable(false);
thisButton.setOnAction(new startGame());
pane.setLeft(thisButton);
return pane;
}
#Override
public void start(Stage primaryStage) {
// Create a scene and place it in the stage
Scene scene = new Scene(getPane(), 960, 800);
primaryStage.setTitle("Dodger"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.setResizable(false);
primaryStage.show(); // Display the stage
scene.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.UP) {
upPressed.set(true);
}
if (e.getCode() == KeyCode.DOWN) {
downPressed.set(true);
}
if (e.getCode() == KeyCode.RIGHT) {
rightPressed.set(true);
}
if (e.getCode() == KeyCode.LEFT) {
leftPressed.set(true);
}
});
scene.setOnKeyReleased(e -> {
if (e.getCode() == KeyCode.UP) {
upPressed.set(false);
}
if (e.getCode() == KeyCode.DOWN) {
downPressed.set(false);
}
if (e.getCode() == KeyCode.RIGHT) {
rightPressed.set(false);
}
if (e.getCode() == KeyCode.LEFT) {
leftPressed.set(false);
}
});
AnimationTimer timer = new AnimationTimer()
{
#Override
public void handle(long timestamp) {
if (upPressed.get()){
gamePane.moveShipUp();
}
if (downPressed.get()){
gamePane.moveShipDown();
}
if (rightPressed.get()) {
gamePane.moveShipRight();
}
if (leftPressed.get()) {
gamePane.moveShipLeft();
}
}
};
anyPressed.addListener((obs, wasPressed, isNowPressed) ->
{
if (isNowPressed) {
timer.start();
} else {
timer.stop();
}
});
}
class startGame implements EventHandler<ActionEvent>
{
#Override
public void handle(ActionEvent e)
{
gamePane.addSpaceship();
gamePane.startGame();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
BoxPane:
package javafxapplication6;
import java.util.Random;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.layout.Pane;
import javafx.util.Duration;
class BoxPane extends Pane
{
private Spaceship spaceShip;
private Timeline asteroids;
private double x;
private double y;
BoxPane(Spaceship thisSpaceShip)
{
spaceShip = thisSpaceShip;
spaceShip.setRotate(180);
}
public void addSpaceship()
{
getChildren().add(spaceShip);
x = 400 - spaceShip.getWidth()/2;
y = 740;
spaceShip.setTranslateX(x);
spaceShip.setTranslateY(y);
}
public void moveShipLeft()
{
if(x > 0)
{
spaceShip.setTranslateX(x-5);
x = x-5;
}
else
{
spaceShip.setTranslateX(0);
x = 0;
}
}
public void moveShipRight()
{
if(x+spaceShip.getWidth() < getWidth())
{
spaceShip.setTranslateX(x+5);
x = x+5;
}
else
{
spaceShip.setTranslateX(getWidth() - spaceShip.getWidth());
x = getWidth() - spaceShip.getWidth();
}
}
public void moveShipUp()
{
if(y > 0)
{
spaceShip.setTranslateY(y-5);
y = y-5;
}
else
{
spaceShip.setTranslateY(0);
y = 0;
}
}
public void moveShipDown()
{
if(y+spaceShip.getHeight() < getHeight())
{
spaceShip.setTranslateY(y+5);
y = y+5;
}
else
{
spaceShip.setTranslateY(getHeight() - spaceShip.getHeight());
y = getHeight() - spaceShip.getHeight();
}
}
public void startGame()
{
//addSpaceship();
asteroids = new Timeline(new KeyFrame(Duration.seconds(.5), e -> displayAsteroid()));
asteroids.setCycleCount(Timeline.INDEFINITE);
asteroids.play();
}
public void displayAsteroid()
{
Asteroid asteroid = new Asteroid();
getChildren().add(asteroid);
Random rand = new Random();
int randomNum = rand.nextInt((int) (getWidth() - asteroid.getWidth()));
asteroid.setY(-200);
asteroid.setX(randomNum);
asteroid.setTranslateY(asteroid.getY());
asteroid.setTranslateX(asteroid.getX());
Timeline timeline = new Timeline();
KeyFrame keyFrame = new KeyFrame(Duration.millis(50), event -> {
if(asteroid.getY() > getHeight()|| asteroid.getBoundsInParent().intersects(spaceShip.getBoundsInParent()))
{
timeline.stop();
getChildren().remove(asteroid);
}
else
{
asteroid.setY(asteroid.getY()+5);
asteroid.setTranslateY(asteroid.getY());
}
});
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(keyFrame);
timeline.play();
}
}
asteroid class:
package javafxapplication6;
import javafx.geometry.Pos;
import java.util.Random;
import java.util.Vector;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
public class Asteroid extends StackPane
{
private Ellipse asteroid = new Ellipse();
private Ellipse hole1 = new Ellipse();
private Ellipse hole2 = new Ellipse();
private Ellipse hole3 = new Ellipse();
private int speed;
private double y = 0;
private double x = 0;
Asteroid()
{
Random rand = new Random();
int asteroidNum = rand.nextInt(10);
if(asteroidNum < 6)
{
asteroidNum = 0;
}
else if(asteroidNum < 8)
{
asteroidNum = 1;
}
else
{
asteroidNum = 2;
}
StackPane thisAsteroid = new StackPane();
VBox vbox = new VBox();
HBox hbox = new HBox();
vbox.setAlignment(Pos.CENTER);
hbox.setAlignment(Pos.CENTER);
asteroid.setFill(Color.GREY);
asteroid.setStroke(Color.DIMGREY);
hole1.setFill(Color.DIMGREY);
hole1.setStroke(Color.BLACK);
hole2.setFill(Color.DIMGREY);
hole2.setStroke(Color.BLACK);
hole3.setFill(Color.DIMGREY);
hole3.setStroke(Color.BLACK);
switch(asteroidNum)
{
case 0: asteroid1();
vbox.setSpacing(10);
hbox.setSpacing(10);
break;
case 1: asteroid2();
vbox.setSpacing(15);
hbox.setSpacing(15);
break;
case 2: asteroid3();
vbox.setSpacing(25);
hbox.setSpacing(25);
break;
}
int holeLayout = rand.nextInt(3);
switch(holeLayout)
{
case 0: hbox.getChildren().addAll(hole1, hole2);
vbox.getChildren().addAll(hole3, hbox);
thisAsteroid.getChildren().addAll(asteroid, vbox);
break;
case 1: vbox.getChildren().addAll(hole2, hole3);
hbox.getChildren().addAll(vbox, hole1);
thisAsteroid.getChildren().addAll(asteroid, hbox);
break;
case 2: vbox.getChildren().addAll(hole1, hole3);
hbox.getChildren().addAll(hole2, vbox);
thisAsteroid.getChildren().addAll(asteroid, hbox);
break;
case 3: hbox.getChildren().addAll(hole1, hole2);
vbox.getChildren().addAll(hbox, hole3);
thisAsteroid.getChildren().addAll(asteroid, vbox);
break;
}
this.getChildren().add(thisAsteroid);
}
public void asteroid1()
{
speed = 10;
asteroid.setRadiusX(40);
asteroid.setRadiusY(35);
asteroid.setStrokeWidth(3);
hole1.setRadiusX(7);
hole1.setRadiusY(8);
hole2.setRadiusX(9);
hole2.setRadiusY(6);
hole3.setRadiusX(6);
hole3.setRadiusY(5);
}
public void asteroid2()
{
speed = 6;
asteroid.setRadiusX(60);
asteroid.setRadiusY(50);
asteroid.setStrokeWidth(5);
hole1.setRadiusX(10);
hole1.setRadiusY(12);
hole2.setRadiusX(12);
hole2.setRadiusY(10);
hole3.setRadiusX(14);
hole3.setRadiusY(13);
}
public void asteroid3()
{
speed = 4;
asteroid.setRadiusX(100);
asteroid.setRadiusY(90);
asteroid.setStrokeWidth(8);
hole1.setRadiusX(20);
hole1.setRadiusY(18);
hole2.setRadiusX(18);
hole2.setRadiusY(22);
hole3.setRadiusX(23);
hole3.setRadiusY(19);
}
public void setY(double nY)
{
y = nY;
}
public void setX(double nX)
{
x = nX;
}
public double getX()
{
return x;
}
public double getY()
{
return y;
}
public int getSpeed()
{
return speed;
}
}
spaceship class:
package javafxapplication6;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
public class Spaceship extends StackPane
{
private Rectangle leftWingBottom = new Rectangle();
private Rectangle leftWingGun = new Rectangle();
private Rectangle leftWingDesign = new Rectangle();
private Rectangle leftWingAttachment = new Rectangle();
private Rectangle leftTransparent = new Rectangle();
private Rectangle rightWingBottom = new Rectangle();
private Rectangle rightWingGun = new Rectangle();
private Rectangle rightWingDesign = new Rectangle();
private Rectangle rightWingAttachment = new Rectangle();
private Rectangle rightTransparent = new Rectangle();
private Rectangle centerCompartmentBottom = new Rectangle();
private Rectangle centerCompartmentDesign = new Rectangle();
private Ellipse centerCompartmentTop = new Ellipse();
Spaceship()
{
HBox ship = new HBox();
VBox leftWing = new VBox();
VBox rightWing = new VBox();
VBox leftAttachment = new VBox();
VBox rightAttachment = new VBox();
StackPane leftWingStack = new StackPane();
StackPane rightWingStack = new StackPane();
StackPane centerCompartmentShip = new StackPane();
leftTransparent.setFill(Color.TRANSPARENT);
rightTransparent.setFill(Color.TRANSPARENT);
// creates the right wing
rightWingBottom.setHeight(30);
rightWingBottom.setWidth(8);
rightWingBottom.setStrokeWidth(1);
rightWingDesign.setHeight(25);
rightWingDesign.setWidth(3);
rightWingStack.setAlignment(Pos.CENTER);
rightWingStack.getChildren().addAll(rightWingBottom, rightWingDesign);
rightWingGun.setHeight(5);
rightWingGun.setWidth(2);
rightWing.setAlignment(Pos.TOP_CENTER);
rightWing.getChildren().addAll(rightWingStack, rightWingGun);
// creates the left wing and gun
leftWingBottom.setHeight(30);
leftWingBottom.setWidth(8);
leftWingBottom.setStrokeWidth(1);
leftWingDesign.setHeight(25);
leftWingDesign.setWidth(3);
leftWingStack.setAlignment(Pos.CENTER);
leftWingStack.getChildren().addAll(leftWingBottom, leftWingDesign);
leftWingGun.setHeight(5);
leftWingGun.setWidth(2);
leftWing.setAlignment(Pos.TOP_CENTER);
leftWing.getChildren().addAll(leftWingStack, leftWingGun);
// attaches the cockpit and right wing together
rightTransparent.setHeight(5);
rightTransparent.setWidth(5);
rightWingAttachment.setHeight(3);
rightWingAttachment.setWidth(5);
rightAttachment.setAlignment(Pos.TOP_CENTER);
rightAttachment.getChildren().addAll(rightTransparent, rightWingAttachment);
// attaches the cockpit and left wing together
leftTransparent.setHeight(5);
leftTransparent.setWidth(5);
leftWingAttachment.setHeight(3);
leftWingAttachment.setWidth(5);
leftAttachment.setAlignment(Pos.TOP_CENTER);
leftAttachment.getChildren().addAll(leftTransparent, leftWingAttachment);
// creates the cockpit
centerCompartmentBottom.setHeight(25);
centerCompartmentBottom.setWidth(20);
centerCompartmentBottom.setStrokeWidth(2);
centerCompartmentTop.setRadiusX(10);
centerCompartmentTop.setRadiusY(25);
centerCompartmentTop.setStrokeWidth(2);
centerCompartmentDesign.setHeight(25);
centerCompartmentDesign.setWidth(5);
centerCompartmentShip.setAlignment(Pos.TOP_CENTER);
centerCompartmentShip.getChildren().addAll(centerCompartmentTop, centerCompartmentBottom, centerCompartmentDesign);
rightWingBottom.setFill(Color.WHITE);
rightWingBottom.setStroke(Color.GREY);
leftWingBottom.setFill(Color.WHITE);
leftWingBottom.setStroke(Color.GREY);
rightWingGun.setFill(Color.WHITE);
leftWingGun.setFill(Color.WHITE);
rightWingDesign.setFill(Color.TRANSPARENT);
leftWingDesign.setFill(Color.TRANSPARENT);
rightWingAttachment.setFill(Color.WHITE);
rightWingAttachment.setStroke(Color.GREY);
leftWingAttachment.setFill(Color.WHITE);
leftWingAttachment.setStroke(Color.GREY);
centerCompartmentBottom.setFill(Color.WHITE);
centerCompartmentBottom.setStroke(Color.GREY);
centerCompartmentTop.setFill(Color.WHITE);
centerCompartmentTop.setStroke(Color.GREY);
centerCompartmentDesign.setFill(Color.TRANSPARENT);
// adds everything to final hbox
ship.getChildren().addAll(rightWing,
rightAttachment,
centerCompartmentShip,
leftAttachment,
leftWing);
// adds it to the SpaceShip object
this.getChildren().add(ship);
}
}
Hope this helps, thanks!
I'm new to GWT and I need to create a sortable dynamic celltable.
I saw an example of IndexedColumn class. I generated a Dynamic cell table (List of ArrayList of String), but couldn't make it sort.
does anybody have a simple implementation example?
Thanks
Found my mistake...
Here is my working example:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListDataProvider;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class DynamicTable implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
List<ArrayList<String>> data = this.getThedata();
CellTable<List<String>> table = new CellTable<List<String>>();
ArrayList<String> dataHeaders = data.remove(0);
ArrayList<IdxColumn> columnList = new ArrayList<IdxColumn>();
ListDataProvider<List<String>> dataProvider = new ListDataProvider<List<String>>();
dataProvider.addDataDisplay(table);
List<List<String>> list = dataProvider.getList();
for (List<String> l : data) {
list.add(l);
}
ListHandler<List<String>> columnSortHandler = new ListHandler<List<String>>(list);
table.getColumnSortList().clear();
for (int i = 0; i < data.get(0).size(); i++) {
final int index = i;
IdxColumn iCol = new IdxColumn(index);
columnList.add(iCol);
table.addColumn(iCol, dataHeaders.get(index) + " (" +iCol.getIndex() + ")");
columnSortHandler.setComparator(iCol, new Comparator<List<String>>() {
public int compare(List<String> o1, List<String> o2) {
if (o1 == o2) {
return 0;
}
if (o1 != null) {
return (o2 != null) ? o1.get(0).compareTo(o2.get(0)) : 1;
}
return -1;
}
});
iCol.setSortable(true);
table.getColumnSortList().push(iCol);
}
table.addColumnSortHandler(columnSortHandler);
table.setRowCount(data.size(), true);
table.setRowData(0, data);
RootPanel.get().add(table);
}
// build the data
private List<ArrayList<String>> getThedata() {
List<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
ArrayList<String> dataHeaders = new ArrayList<String>();
dataHeaders.add("Header 1");
dataHeaders.add("Header 2");
dataHeaders.add("Header 3");
dataHeaders.add("Header 4");
dataHeaders.add("Header 5");
dataHeaders.add("Header 6");
data.add(dataHeaders);
for (int i = 0; i < 20; i++) {
ArrayList<String> dataRow = new ArrayList<String>();
dataRow.add("Col1 Row" + i);
dataRow.add("Col2 Row" + i);
dataRow.add("Col3 Row" + i);
dataRow.add("Col4 Row" + i);
dataRow.add("Col5 Row" + i);
dataRow.add("Col6 Row" + i);
data.add(dataRow);
}
return data;
}
}
And the IdxColumn class:
import java.util.List;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.user.cellview.client.Column;
public class IdxColumn extends Column<List<String>, String> {
private final int index;
public IdxColumn( int index) {
super(new TextCell());
this.index = index;
}
#Override
public String getValue(List<String> object) {
return object.get(index);
}
public int getIndex() {
return this.index;
}
}
What I need is a toast or something like that with content of an array list, that opens when I click on a LinearLayout item. But I don't know how to implement it with the holder view.
public class CanteenListAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
private ArrayList<CanteenMenu> listData;
private LayoutInflater layoutInflater;
private Context context;
public CanteenListAdapter(ArrayList<CanteenMenu> listData, Context bContext){
this.listData = listData;
layoutInflater = LayoutInflater.from(bContext);
this.context = bContext;
Collections.sort(this.listData);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View cView, ViewGroup parent) {
ViewHolder holder;
if(cView==null){
cView = layoutInflater.inflate(R.layout.activity_canteen_tab_listitem, null);
holder = new ViewHolder();
holder.date = (TextView) cView.findViewById(R.id.canteen_header);
holder.ll = (LinearLayout) cView.findViewById(R.id.canteen_linearLayout);
int j = 0;
for (int i = 0; i < listData.get(position).getCategory().length; i++) {
TextView description = new TextView(context);
TextView category = new TextView(context);
description.setText(listData.get(position).getName()[i]);
category.setText(listData.get(position).getCategory()[i]);
holder.ll.addView(category, j);
holder.ll.addView(description,j + 1);
j += 2;
}
cView.setTag(holder);
} else{
holder = (ViewHolder) cView.getTag();
}
int j = 0;
for(int i = 0; i < listData.get(position).getCategory().length; i++) {
if(holder.ll.getChildAt(j) != null) {
((TextView) holder.ll.getChildAt(j)).setText(listData.get(position).getCategory()[i]);
((TextView) holder.ll.getChildAt(j + 1)).setText(listData.get(position).getName()[i]);
}
j += 2;
}
return cView;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
static class ViewHolder {
LinearLayout ll;
TextView date;
TextView name;
TextView category;
}
}
Can anyone help ?
i have have design a class whos constructor produce 52 Cards object each orject has its own color, value, isTrump(boolean) and imageIcon which store image of each card. now there is another class called Que who stores all the objects of cards into a que and shuffle them. there is a method which deals the cards object among 4 players into array of object(Cards). now i used LayeredPane and Jlabels to show them and a mouse-listener also attached with each.
Now i only want a tip how can i start each trick. means i place one card then three other robots placed there cards automatically after analysing my card on the bases of some predefined rules.
please any suggestions
public class Cards {
public Cards(int a, int b){
this.cardvalue = a;
this.color = b;
this.isTrump = false;
switch(a){
case 11: this.facevalue = 1;
break;
case 12: this.facevalue = 2;
break;
case 13: this.facevalue = 3;
break;
case 14: this.facevalue = 4;
break;
default : this.facevalue = 0;
}
switch(b){
case 1: this.colorName = "Spade";
this.CardImage= new ImageIcon(getClass().getResource("/testing/Cards/Spade/Spade ("+a+").jpg"));
break;
case 2: this.colorName = "Heart";
this.CardImage= new ImageIcon(getClass().getResource("/testing/Cards/Heart/Heart ("+a+").jpg"));
break;
case 3: this.colorName = "Diamond";
this.CardImage= new ImageIcon(getClass().getResource("/testing/Cards/Diamond/Diamond ("+a+").jpg"));
break;
default : this.colorName = "Club";
this.CardImage= new ImageIcon(getClass().getResource("/testing/Cards/Club/Club ("+a+").jpg"));
}
}
public void isTrump(){
this.isTrump = true;
}
public int getCardValue(){
return this.cardvalue;
}
public int getColor(){
return this.color;
}
public int getFaceValue(){
return this.facevalue;
}
public boolean getisTrump(){
return this.isTrump;
}
public String getColorName(){
return this.colorName;
}
public ImageIcon getCardImage(){
return this.CardImage;
}
public ImageIcon getBackSide(){
return backSide;
}
private String colorName;
private int cardvalue;
private int color; // 1 For Spade 2 For Heart 3 For Diamond 4 For Club
private int facevalue;
private boolean isTrump;
private ImageIcon CardImage;
private ImageIcon backSide = new
ImageIcon(getClass().getResource("/testing/Cards/Backside.jpg"));
}
Class which deal the card is
public class CardsInHand {
public CardsInHand(){
totalCards = new Que(52);
int a =1; int b=2;
for (int j = 0;j<52;j++){
if(j==13||j==26||j==39) a++;
if(b==15) b=2;
totalCards.put(new Cards(b,a));
b++;
}
totalCards.QueShuffle();
}
public static void Deal(){
card = new CardsInHand();
setPlayers();
}
private static void setPlayers(){
for(int i =0;i<13;i++){
Hands[0][i] = totalCards.get();
Hands[1][i] = totalCards.get();
Hands[2][i] = totalCards.get();
Hands[3][i] = totalCards.get();
}
sortingarr();
}
private static void Sorting(Cards arr[]){
//here some Sorting algorithm i used
}
private static void sortingarr(){
Sorting(Hands[0]);
Sorting(Hands[1]);
Sorting(Hands[2]);
Sorting(Hands[3]);
NumberSorting(Hands[0]);
NumberSorting(Hands[1]);
NumberSorting(Hands[2]);
NumberSorting(Hands[3]);
}
private static void NumberSorting(Cards arr[]){
//some algorith i used for number sorting
}
public static Cards[] getPlayer1(){
return Hands[0];
}
public static Cards[] getPlayer2(){
return Hands[1];
}
public static Cards[] getPlayer3(){
return Hands[2];
}
public static Cards[] getPlayer4(){
return Hands[3];
}
public static Cards[][] getAllHands(){
return Hands;
}
private final static Cards[] Player1 = new Cards[13];
private final static Cards[] Player2 = new Cards[13];
private final static Cards[] Player3 = new Cards[13];
private final static Cards[] Player4 = new Cards[13];
private final static Cards[][] Hands = {Player1,Player2,Player3,Player4};
private static Que totalCards;
private static CardsInHand card;
}
the class which is showing the cards after dealing is
public class ShowCards {
private JFrame frame = new JFrame();
private static JLayeredPane lpane = new JLayeredPane();
private static JLabel[] Player1 = new JLabel[13];
private static JLabel[] Player2 = new JLabel[13];
private static JLabel[] Player3 = new JLabel[13];
private static JLabel[] Player4 = new JLabel[13];
private static JButton button = new JButton("Deal Again");
public ShowCards()
{
CardsInHand.Deal();
frame.setPreferredSize(new Dimension(800, 640));
frame.setLayout(new BorderLayout());
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.LINE_AXIS));
frame.add(lpane, BorderLayout.CENTER);
frame.add(button);
lpane.add(button, new Integer(14), 0);
button.setBounds(200, 250, 100, 70);
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
});
lpane.setBounds(30, 30, 270, 270);
cardDeal();
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static void cardDeal(){
loadJLabels1();
loadJLabels2();
loadJLabels3();
loadJLabels4();
}
static void loadJLabels1(){
int k = 30;
for(int i=0;i<13;i++){
Player1[i] = new JLabel();
Player1[i].setIcon(CardsInHand.getPlayer1()[i].getCardImage());
Player1[i].setBounds(k, 20, 170, 100);
Player1[i].setOpaque(true);
Player1[i].addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
int count = evt.getClickCount();
if (count == 1){
int Index = getIndex(Player1, (JLabel)evt.getSource());
Player1[Index].setIcon(CardsInHand.getPlayer1()[Index].getBackSide());
}
}
});
lpane.add(Player1[i], new Integer(i), 0);
k = k+30;
}
}
static void loadJLabels2(){
int k = 140;
for(int i=0;i<13;i++){
Player2[i] = new JLabel();
Player2[i].setIcon(CardsInHand.getPlayer2()[i].getCardImage());
Player2[i].setBounds(30, k, 170, 100);
Player2[i].setOpaque(true);
Player2[i].addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
int count = evt.getClickCount();
if (count == 1){
int Index = getIndex(Player2, (JLabel)evt.getSource());
Player2[Index].setIcon(CardsInHand.getPlayer2()[Index].getBackSide());
}
}
});
lpane.add(Player2[i], new Integer(i), 0);
k = k+20;
}
}
static void loadJLabels3(){
int k = 140;
for(int i=0;i<13;i++){
Player3[i] = new JLabel();
Player3[i].setIcon(CardsInHand.getPlayer3()[i].getCardImage());
Player3[i].setBounds(400, k, 170, 100);
Player3[i].setOpaque(true);
Player3[i].addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
int count = evt.getClickCount();
if (count == 1){
int Index = getIndex(Player3, (JLabel)evt.getSource());
Player3[Index].setIcon(CardsInHand.getPlayer2()[Index].getBackSide());
}
}
});
lpane.add(Player3[i], new Integer(i), 0);
k = k+20;
}
}
static void loadJLabels4(){
int k = 30;
for(int i=0;i<13;i++){
Player4[i] = new JLabel();
Player4[i].setIcon(CardsInHand.getPlayer4()[i].getCardImage());
Player4[i].setBounds(k, 500, 170, 100);
Player4[i].setOpaque(true);
Player4[i].addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
int count = evt.getClickCount();
if (count == 1){
int Index = getIndex(Player4, (JLabel)evt.getSource());
Player4[Index].setIcon(CardsInHand.getPlayer2()[Index].getBackSide());
}
}
});
lpane.add(Player4[i], new Integer(i), 0);
k = k+30;
}
}
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
CardsInHand.Deal();
cardDeal();
}
static int getIndex(JLabel[] arr, JLabel obj){
int index=0;
for(JLabel cmp: arr){
if(cmp == obj) break;
index++;
}
return index;
}
}
Now i also creat a player class which creat three Bots to play and one will be the human. the class is as
public class Players {
public Players(Cards[] arr){
this.scoreInHand = getScoreInHand(arr);
getCardOfEachSuit(arr, this.cardsOfEachSuit);
this.isBalanceHand = getIsBalanceHand(arr);
this.longestSuit = getLongestSuit(arr);
this.numberOfTrump = getNumberOfTrump(arr);
this.smallestSuit = getSmallestSuit(arr);
this.strongestSuit = getStrongestSuit(arr);
this.weakestSuit = getWeakestSuit(arr);
for(int i=0;i<13;i++){
this.remainingSpade[i] = true;
this.remainingHeart[i] = true;
this.remainingClub[i] = true;
this.remainingDiamond[i] = true;
}
for(int i=0;i<4;i++){
this.rightOpCutSuit[i]= false;
this.leftOpCutSuit[i] = false;
this.frontOpCutSuit[i] = false;
}
this.coatCaution = false;
this.gcCaution = false;
this.numberOfTrumpExist = 13;
this.openingBet =0;
this.respondingBet =0;
this.trickStarter = false;
}
public static void createRobot(){
CardsInHand.Deal();
for(int i=0; i<3;i++){
Robots[i] = new Players(CardsInHand.getAllHands()[i+1]);
}
}
private int getScoreInHand(Cards[] arr){
int temp = 0;
for(Cards x: arr){
temp = temp + x.getFaceValue();
}
return temp;
}
private int getStrongestSuit(Cards[] arr){
int strong=0;
int S=0;int C=0;int D=0;int H=0;
for(Cards x: arr){
if(x.getColorName()=="Spade") S = S + x.getFaceValue();
else if(x.getColorName()=="Heart") H = H + x.getFaceValue();
else if(x.getColorName()=="Club") C = C + x.getFaceValue();
else D = D + x.getFaceValue();
}
int[] temp = {S,H,D,C};
int max = temp[0];
for(int i=0;i<4;i++){
if(max<temp[i]){
max=temp[i];
strong = i;
}
}
return strong+1;
}
private int getWeakestSuit(Cards[] arr){
int weak=0;
int S=0;int C=0;int D=0;int H=0;
for(Cards x: arr){
if(x.getColorName()=="Spade") S = S + x.getFaceValue();
else if(x.getColorName()=="Heart") H = H + x.getFaceValue();
else if(x.getColorName()=="Club") C = C + x.getFaceValue();
else D = D + x.getFaceValue();
}
int[] temp = {S,H,D,C};
int min = temp[0];
for(int i=0;i<4;i++){
if(min>temp[i]){
min=temp[i];
weak = i;
}
}
return weak+1;
}
private int getLongestSuit(Cards[] arr){
int Longest = 0;
int[] temp = new int[4];
getCardOfEachSuit(arr, temp);
int max = temp[0];
for(int i=0;i<4;i++){
if(max<temp[i]){
max=temp[i];
Longest = i;
}
}
return Longest+1;
}
private int getSmallestSuit(Cards[] arr){
int Smallest = 0;
int[] temp = new int[4];
getCardOfEachSuit(arr, temp);
int max = temp[0];
for(int i=0;i<4;i++){
if(max>temp[i]){
max=temp[i];
Smallest = i;
}
}
return Smallest+1;
}
private boolean getIsBalanceHand(Cards[] arr){
int S=0;int C=0;int D=0;int H=0;
for(Cards x: arr){
if(x.getColorName()=="Spade") S++;
else if(x.getColorName()=="Heart") H++;
else if(x.getColorName()=="Club") C++;
else D++;
}
if((S<=4&&S>=3)&&(H<=4&&H>=3)&&(D<=4&&D>=3)&&(C<=4&&C>=3)) return true;
else return false;
}
private void getCardOfEachSuit(Cards[] arr, int[] array){
int S=0;int C=0;int D=0;int H=0;
for(Cards x: arr){
if(x.getColorName()=="Spade") S++;
else if(x.getColorName()=="Heart") H++;
else if(x.getColorName()=="Club") C++;
else D++;
}
array[0] = S;
array[1] = H;
array[2] = D;
array[3] = C;
}
private int getNumberOfTrump(Cards[] arr){
int temp = 0;
for(Cards x: arr){
if(x.getisTrump() == true) temp = temp+1;
}
return temp;
}
public void setTrickStarter(boolean a){
this.trickStarter = a;
}
public boolean getTrickStarter(){
return this.trickStarter;
}
private static Players[] Robots = new Players[3]; //
private int[] cardsOfEachSuit = new int[4]; // ok
private boolean[] remainingSpade = new boolean[13]; //
private boolean[] remainingHeart = new boolean[13]; //
private boolean[] remainingDiamond = new boolean[13]; //
private boolean[] remainingClub = new boolean[13]; //
private int scoreInHand; // ok
private int longestSuit; // ok
private int smallestSuit; // ok
private int strongestSuit; // ok
private int weakestSuit; // ok
private boolean isBalanceHand; // ok
private int numberOfTrump; // ok
private int numberOfTrumpExist; //
private boolean[] rightOpCutSuit = new boolean[4]; //
private boolean[] frontOpCutSuit = new boolean[4]; //
private boolean[] leftOpCutSuit = new boolean[4]; //
private int openingBet; //
private int respondingBet; //
private boolean gcCaution; //
private boolean coatCaution; //
private boolean trickStarter;
}
Now please guide me little forward what is can do to start playing.
here is my app. how to add table view or grids in the following.
should i draw every thing plz help
this is my code
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.device.api.util.*;
import java.util.*;
/*An application in which user enters the data. this data is displayed when user press the save button*/
public class Display extends UiApplication {
/*declaring Strings to store the data of the user*/
String getFirstName;
String getLastName;
String getEmail;
String getGender;
String getStatus;
/*declaring text fields for user input*/
private AutoTextEditField firstName;
private AutoTextEditField lastName;
private EmailAddressEditField email;
/*declaring choice field for user input*/
private ObjectChoiceField gender;
/*declaring check box field for user input*/
private CheckboxField status;
//Declaring button fields
private ButtonField save;
private ButtonField close;
private ButtonField List;
/*declaring vector*/
private static Vector _data;
/*declaring persistent object*/
private static PersistentObject store;
/*creating an entry point*/
public static void main(String[] args)
{
Display obj = new Display();
obj.enterEventDispatcher();
}
/*creating default constructor*/
public Display()
{
/*Creating an object of the main screen class to use its functionalities*/
MainScreen mainScreen = new MainScreen();
//setting title of the main screen
mainScreen.setTitle(new LabelField("Enter Your Data"));
//creating text fields for user input
firstName = new AutoTextEditField("First Name: ", "");
lastName= new AutoTextEditField("Last Name: ", "");
email= new EmailAddressEditField("Email:: ", "");
//creating choice field for user input
String [] items = {"Male","Female"};
gender= new ObjectChoiceField("Gender",items);
//creating Check box field
status = new CheckboxField("Active",true);
//creating Button fields and adding functionality using listeners
save = new ButtonField("Save",ButtonField.CONSUME_CLICK);
save.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
save();
}
});
close = new ButtonField("Close",ButtonField.CONSUME_CLICK);
close.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
onClose();
}
});
List = new ButtonField("List",ButtonField.CONSUME_CLICK);
List.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context){
pushScreen(new ListScreen());
}
});
//adding the input fields to the main screen
mainScreen.add(firstName);
mainScreen.add(lastName);
mainScreen.add(email);
mainScreen.add(gender);
mainScreen.add(status);
//adding buttons to the main screen
HorizontalFieldManager horizontal = new HorizontalFieldManager(HorizontalFieldManager.FIELD_HCENTER);
horizontal.add(close);
horizontal.add(save);
horizontal.add(List);
mainScreen.add(horizontal);
//adding menu items
mainScreen.addMenuItem(saveItem);
mainScreen.addMenuItem(getItem);
mainScreen.addMenuItem(Deleteall);
//pushing the main screen
pushScreen(mainScreen);
}
private MenuItem Deleteall = new MenuItem("Delete all",110,10)
{
public void run()
{
int response = Dialog.ask(Dialog.D_YES_NO,"Are u sure u want to delete entire Database");
if(Dialog.YES == response){
PersistentStore.destroyPersistentObject(0xdec6a67096f833cL);
onClose();
}
else
Dialog.inform("Thank God");
}
};
//adding functionality to menu item "saveItem"
private MenuItem saveItem = new MenuItem("Save", 110, 10)
{
public void run()
{
//Calling save method
save();
}
};
//adding functionality to menu item "saveItem"
private MenuItem getItem = new MenuItem("Get", 110, 11)
{
//running thread for this menu item
public void run()
{
//synchronizing thread
synchronized (store)
{
//getting contents of the persistent object
_data = (Vector) store.getContents();
try{
for (int i = _data.size()-1; i >-1; i--)
{
StoreInfo info = (StoreInfo)_data.elementAt(i);
//checking for empty object
if (!_data.isEmpty())
{
//if not empty
//create a new object of Store Info class
//storing information retrieved in strings
getFirstName = (info.getElement(StoreInfo.NAME));
getLastName = (info.getElement(StoreInfo.LastNAME));
getEmail = (info.getElement(StoreInfo.EMail));
getGender = (info.getElement(StoreInfo.GenDer));
getStatus = (info.getElement(StoreInfo.setStatus));
//calling the show method
show();
}
}
}
catch(Exception e){}
}
}
};
public void save()
{
//creating an object of inner class StoreInfo
StoreInfo info = new StoreInfo();
//getting the test entered in the input fields
info.setElement(StoreInfo.NAME, firstName.getText());
info.setElement(StoreInfo.LastNAME,lastName.getText());
info.setElement(StoreInfo.EMail, email.getText());
info.setElement(StoreInfo.GenDer,gender.toString());
if(status.getChecked())
info.setElement(StoreInfo.setStatus, "Active");
else
info.setElement(StoreInfo.setStatus, "In Active");
//adding the object to the end of the vector
_data.addElement(info);
//synchronizing the thread
synchronized (store)
{
store.setContents(_data);
store.commit();
}
//resetting the input fields
Dialog.inform("Success!");
firstName.setText(null);
lastName.setText(null);
email.setText("");
gender.setSelectedIndex("Male");
status.setChecked(true);
}
//coding for persistent store
static {
store =
PersistentStore.getPersistentObject(0xdec6a67096f833cL);
synchronized (store) {
if (store.getContents() == null) {
store.setContents(new Vector());
store.commit();
}
}
_data = new Vector();
_data = (Vector) store.getContents();
}
//new class store info implementing persistable
private static final class StoreInfo implements Persistable
{
//declaring variables
private Vector _elements;
public static final int NAME = 0;
public static final int LastNAME = 1;
public static final int EMail= 2;
public static final int GenDer = 3;
public static final int setStatus = 4;
public StoreInfo()
{
_elements = new Vector(5);
for (int i = 0; i < _elements.capacity(); ++i)
{
_elements.addElement(new String(""));
}
}
public String getElement(int id)
{
return (String) _elements.elementAt(id);
}
public void setElement(int id, String value)
{
_elements.setElementAt(value, id);
}
}
//details for show method
public void show()
{
Dialog.alert("Name is "+getFirstName+" "+getLastName+"\nGender is "+getGender+"\nE-mail: "+getEmail+"\nStatus is "+getStatus);
}
public void list()
{
Dialog.alert("haha");
}
//creating save method
//overriding onClose method
public boolean onClose()
{
System.exit(0);
return true;
}
class ListScreen extends MainScreen
{
String firstUserName="Ali";
String lastUserName="Asif";
String userEmail="assad";
String userGender="asdasd";
String userStatus="active";
private AutoTextEditField userFirstName;
private AutoTextEditField userLastName;
private EmailAddressEditField userMail;
private ObjectChoiceField usersGender;
private CheckboxField usersStatus;
private ButtonField btnBack;
public ListScreen()
{
SeparatorField sps = new SeparatorField();
HorizontalFieldManager hr = new HorizontalFieldManager(HorizontalFieldManager.FIELD_HCENTER|HorizontalFieldManager.HORIZONTAL_SCROLLBAR);
VerticalFieldManager vr = new VerticalFieldManager();
setTitle(new LabelField("List of All Data"));
list();
btnBack = new ButtonField("Back",ButtonField.CONSUME_CLICK);
btnBack.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field,int context)
{
UiApplication.getUiApplication().popScreen(getScreen());
}
});
hr.add(btnBack);
add(hr);
add(sps);
}
public void list()
{
_data = (Vector) store.getContents();
try{
int sn=0;
for (int i = _data.size()-1; i >-1; i--,sn++)
{
StoreInfo info = (StoreInfo)_data.elementAt(i);
//checking for empty object
if (!_data.isEmpty())
{
//if not empty
//create a new object of Store Info class
//storing information retrieved in strings
firstUserName = (info.getElement(StoreInfo.NAME));
lastUserName = (info.getElement(StoreInfo.LastNAME));
userEmail = (info.getElement(StoreInfo.EMail));
userGender = (info.getElement(StoreInfo.GenDer));
userStatus = (info.getElement(StoreInfo.setStatus));
//calling the listAll method
listAll();
}
}
}
catch(Exception e){}
}
public void listAll()
{
SeparatorField sp = new SeparatorField();
SeparatorField sps = new SeparatorField();
HorizontalFieldManager hrs = new HorizontalFieldManager(HorizontalFieldManager.HORIZONTAL_SCROLL);
hrs.add(new RichTextField(""+firstUserName+" "+lastUserName+" | "+userEmail+" | "+userGender+" | "+userStatus));
//add(new RichTextField("Email: "+userEmail));
//add(new RichTextField("Gender: "+userGender));
//add(new RichTextField("Status: "+userStatus));
//SeparatorField sp = new SeparatorField();
add(hrs);
add(sp);
add(sps);
}
public boolean onClose()
{
System.exit(0);
return true;
}
}
}
There is a nice GridFieldManager by Anthony Rizk.
Code:
public void list()
{
if (null != mGrid && null != mGrid.getManager())
mGrid.getManager().delete(mGrid);
int colWidth = net.rim.device.api.system.Display.getWidth() / 4;
mGrid = new GridFieldManager(new int[] { 0, colWidth, colWidth,
colWidth, colWidth }, VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
mGrid.add(new NullField(FOCUSABLE));
mGrid.add(new LabelField("Name"));
mGrid.add(new LabelField("E-Mail"));
mGrid.add(new LabelField("Gender"));
mGrid.add(new LabelField("Active"));
add(mGrid);
_data = (Vector) store.getContents();
try {
int sn = 0;
for (int i = _data.size() - 1; i > -1; i--, sn++) {
StoreInfo info = (StoreInfo) _data.elementAt(i);
// checking for empty object
if (!_data.isEmpty()) {
// if not empty
// create a new object of Store Info class
// storing information retrieved in strings
firstUserName = (info.getElement(StoreInfo.NAME));
lastUserName = (info.getElement(StoreInfo.LastNAME));
userEmail = (info.getElement(StoreInfo.EMail));
userGender = (info.getElement(StoreInfo.GenDer));
userStatus = (info.getElement(StoreInfo.setStatus));
// calling the listAll method
mGrid.add(new NullField(FOCUSABLE));
mGrid.add(new LabelField(firstUserName + " "
+ lastUserName));
mGrid.add(new LabelField(userEmail));
mGrid.add(new LabelField(userGender));
mGrid.add(new LabelField(userStatus));
}
}
} catch (Exception e) {
}
}
See also
BlackBerry Grid Layout Manager updated