Skip to content
Snippets Groups Projects
Commit a304bef3 authored by LABOUREL Arnaud's avatar LABOUREL Arnaud
Browse files

Merge branch 'revert-bbd94e44' into 'main'

Revert "Correction TP"

See merge request !1
parents bbd94e44 76b03a61
Branches
No related tags found
1 merge request!1Revert "Correction TP"
Pipeline #1249 passed
Showing
with 687 additions and 1333296 deletions
...@@ -23,5 +23,5 @@ test { ...@@ -23,5 +23,5 @@ test {
} }
application { application {
mainClassName = "Main" mainClassName = "GameOfLifeApplication"
} }
\ No newline at end of file
rootProject.name = 'image' rootProject.name = 'game-of-life'
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 02/10/2018.
*/
public class ByteGrayColor implements GrayColor {
private int grayLevel;
public static final int MAXIMUM_GRAY_LEVEL = 255;
@Override
public int getMaximumGrayLevel() {
return MAXIMUM_GRAY_LEVEL;
}
public static final int MINIMUM_GRAY_LEVEL = 0;
private static final int OPACITY = 1;
public int getGrayLevel() {
// TODO : Renvoyer le niveau de gris de l'instance.
return 0;
}
public ByteGrayColor(){
// TODO : Initialiser l'attribut grayLevel de l'instance avec MINIMUM_GRAY_VALUE.
}
public ByteGrayColor(int grayLevel) {
// TODO : Initialiser l'attribut grayLevel de l'instance.
}
@Override
public Color getColor(){
return new Color(grayLevel/(double) MAXIMUM_GRAY_LEVEL,
grayLevel/(double) MAXIMUM_GRAY_LEVEL,
grayLevel/(double) MAXIMUM_GRAY_LEVEL,
OPACITY);
}
@Override
public void setGrayLevel(int grayLevel) {
// TODO : Changer le niveau de gris de la couleur.
}
@Override
public int compareTo(GrayColor o) {
// TODO : Renvoyer la différence de niveau de gris.
return 0;
}
}
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.PixelWriter;
import java.net.URL;
import java.util.ResourceBundle;
/**
* Created by Arnaud Labourel on 04/10/2018.
*/
public class Display implements Initializable {
@FXML
private Canvas canvas;
MatrixGrayImage image;
@Override
public void initialize(URL location, ResourceBundle resources) {
this.image = MatrixGrayImage.createImageFromPGMFile("images/luminy.pgm");
// TODO : Ajouter les transformations d'image.
render();
}
public void render() {
int pixelWidth = image.getWidth();
int pixelHeight = image.getHeight();
canvas.setWidth(pixelWidth);
canvas.setHeight(pixelHeight);
GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
PixelWriter pixelWriter = graphicsContext.getPixelWriter();
for (int i = 0; i < pixelWidth; i++) {
for (int j = 0; j < pixelHeight; j++) {
renderPixel(i,j, pixelWriter);
}
}
}
private void renderPixel(int x, int y, PixelWriter pixelWriter) {
pixelWriter.setColor(x, y, image.getPixelColor(x, y));
}
}
import controller.Controller;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import model.GameOfLife;
import model.Grid;
import java.io.IOException;
import java.net.URL;
import static java.util.Objects.requireNonNull;
/**
* Entry point for <i>The Game of Life</i> application.
*
*/
public class GameOfLifeApplication extends Application {
private static final int NUMBER_OF_ROWS = 40;
private static final int NUMBER_OF_COLUMNS = 70;
private static final String APP_NAME = "Game of Life";
private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
private final GameOfLife gameOfLife;
private Stage primaryStage;
private Parent view;
/**
* Creates a new {@code GameOfLifeApplication} instance.
*/
public GameOfLifeApplication() {
this(new GameOfLife(new Grid(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS)));
}
/**
* Creates a new {@code GameOfLifeApplication} instance given a {@link GameOfLife} instance.
*
* @param gameOfLife the {@link GameOfLife} instance
* @throws NullPointerException if {@code gameOfLife} is {@code null}
*/
private GameOfLifeApplication(GameOfLife gameOfLife) {
this.gameOfLife = requireNonNull(gameOfLife, "game of life is null");
}
@Override
public void start(Stage primaryStage) throws IOException {
initializePrimaryStage(primaryStage);
initializeView();
showScene();
}
private void initializePrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle(APP_NAME);
this.primaryStage.setOnCloseRequest(event -> Platform.exit());
this.primaryStage.setResizable(false);
this.primaryStage.sizeToScene();
}
private void initializeView() throws IOException {
FXMLLoader loader = new FXMLLoader();
URL location = GameOfLifeApplication.class.getResource(VIEW_RESOURCE_PATH);
loader.setLocation(location);
view = loader.load();
Controller controller = loader.getController();
controller.setGameOfLife(gameOfLife);
}
private void showScene() {
Scene scene = new Scene(view);
primaryStage.setScene(scene);
primaryStage.show();
}
}
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 04/10/2018.
* Interface correspondant à une couleur de gris.
*/
public interface GrayColor extends Comparable<GrayColor> {
int getGrayLevel();
void setGrayLevel(int grayLevel);
int getMaximumGrayLevel();
Color getColor();
}
/**
* Created by Arnaud Labourel on 04/10/2018.
*/
public interface GrayImage extends Image{
void setGrayLevel(int graylevel, int x, int y);
int getGrayLevel(int x, int y);
GrayColor getPixelGrayColor(int x, int y);
}
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 02/10/2018.
*/
public interface Image {
Color getPixelColor(int x, int y);
int getWidth();
int getHeight();
}
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application
{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
Parent root =FXMLLoader.load(getClass().getResource("fxml/Display.fxml"));
primaryStage.setTitle("Image display");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
import javafx.scene.paint.Color;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Scanner;
/**
* Created by Arnaud Labourel on 02/10/2018.
*/
public class MatrixGrayImage implements GrayImage {
private final ByteGrayColor[][] pixels;
private final int width;
private final int height;
@Override
public GrayColor getPixelGrayColor(int x, int y) {
// TODO : Changer le code pour retourner la bonne couleur de gris.
return new ByteGrayColor(ByteGrayColor.MAXIMUM_GRAY_LEVEL);
}
@Override
public void setGrayLevel(int graylevel, int x, int y) {
// TODO : Changer le code pour mettre à jour la couleur.
}
@Override
public int getGrayLevel(int x, int y) {
// TODO : Changer le code pour retourner le bon niveau de gris.
return ByteGrayColor.MAXIMUM_GRAY_LEVEL;
}
@Override
public Color getPixelColor(int x, int y) {
// TODO : Changer le code pour retourner la bonne couleur.
return Color.WHITE;
}
@Override
public int getWidth() {
// TODO : Changer le code pour retourner la bonne largeur.
return 600;
}
@Override
public int getHeight() {
// TODO : Changer le code pour retourner la bonne hauteur.
return 400;
}
public MatrixGrayImage(int width, int height){
/* TODO : Changer le code pour initialiser correctement les attributs de l'instance.
*/
this.width=0;
this.height=0;
this.pixels=null;
}
public static MatrixGrayImage createImageFromPGMFile(String fileName) {
InputStream file = ClassLoader.getSystemResourceAsStream(fileName);
Scanner scan = null;
try {
scan = new Scanner(file);
}
catch (Exception e){
e.printStackTrace();
}
scan.nextLine();
scan.nextLine();
int width = scan.nextInt();
int height = scan.nextInt();
MatrixGrayImage result = new MatrixGrayImage(width, height);
scan.nextInt();
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++) {
result.setGrayLevel(scan.nextInt(), x, y);
}
}
return result;
}
public void writeIntoPGMFormat(String fileName){
try {
FileWriter fileWriter = new FileWriter(fileName);
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.println("P2");
printWriter.println("# CREATOR: TP3 Version 1.0");
printWriter.printf("%d %d\n",this.width, this.height);
printWriter.println(pixels[0][0].getMaximumGrayLevel());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++) {
printWriter.println(getGrayLevel(x,y));
}
}
printWriter.close();
}
catch (Exception e){
e.printStackTrace();
}
}
}
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import model.GameOfLife;
import model.Grid;
import view.MatrixPane;
import static java.util.Objects.requireNonNull;
/**
* Controller for <i>The Game of Life</i> application.
*/
public class Controller {
@FXML
private ToggleButton playToggleButton;
@FXML
private ToggleButton pauseToggleButton;
@FXML
private Label generationNumberLabel;
@FXML
private MatrixPane matrixPane;
private GameOfLife gameOfLife;
@FXML
private void initialize() {
initializePlayAndPauseToggleButtons();
}
private void initializePlayAndPauseToggleButtons() {
ToggleGroup toggleGroup = new PersistentToggleGroup();
toggleGroup.getToggles().addAll(playToggleButton, pauseToggleButton);
pauseToggleButton.setSelected(true);
}
/**
* Sets {@link GameOfLife} instance.
*
* @param gameOfLife {@link GameOfLife} instance
* @throws NullPointerException if {@code gameOfLife} is {@code null}
*/
public void setGameOfLife(GameOfLife gameOfLife) {
this.gameOfLife = requireNonNull(gameOfLife, "game of life is null");
setGenerationNumberLabelTextProperty();
initializeMatrixPane();
}
private void setGenerationNumberLabelTextProperty() {
generationNumberLabel.textProperty().bind(gameOfLife.generationNumberProperty().asString());
}
private void initializeMatrixPane() {
Grid grid = gameOfLife.getGrid();
matrixPane.initialize(grid);
}
@FXML
private void playToggleButtonAction() {
gameOfLife.play();
}
@FXML
private void pauseToggleButtonAction() {
gameOfLife.pause();
}
@FXML
private void resetButtonAction() {
gameOfLife.reset();
pauseToggleButton.setSelected(true);
}
@FXML
private void clearButtonAction() {
gameOfLife.clear();
pauseToggleButton.setSelected(true);
}
}
package controller;
import javafx.collections.ListChangeListener.Change;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
/**
* An extension of {@link ToggleGroup} that ensures that a {@link Toggle} in a group must always be
* selected.
*
*/
class PersistentToggleGroup extends ToggleGroup {
/**
* Creates a new {@code PersistentToggleGroup}.
*/
PersistentToggleGroup() {
getToggles().addListener((Change<? extends Toggle> change) -> {
while (change.next()) {
for (Toggle toggle : change.getAddedSubList()) {
ToggleButton toggleButton = (ToggleButton) toggle;
toggleButton.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseEvent -> {
if (toggleButton.equals(getSelectedToggle())) {
mouseEvent.consume();
}
});
}
}
});
}
}
package model;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
/**
* {@link Cell} instances represent the cells of <i>The Game of Life</i>.
*/
public class Cell {
private final Property<CellState> stateProperty = new SimpleObjectProperty<>(CellState.DEAD);
/**
* Determines whether this {@link Cell} is alive or not.
*
* @return {@code true} if this {@link Cell} is alive and {@code false} otherwise
*/
public boolean isAlive() {
return getState().isAlive;
}
/**
* Sets the state of this {@link Cell}.
*
* @param cellState the new state of this {@link Cell}
*/
public void setState(CellState cellState) {
getStateProperty().setValue(cellState);
}
/**
* Returns the current state of this {@link Cell}.
*
* @return the current state of this {@link Cell}
*/
public CellState getState(){
return getStateProperty().getValue();
}
/**
* Change the state of this {@link Cell} from ALIVE to DEAD or from DEAD to ALIVE.
*/
public void toggleState() {
CellState[] possibleStates = CellState.values();
int stateOrdinal = getState().ordinal();
int numberOfPossibleStates = possibleStates.length;
setState(possibleStates[(stateOrdinal+1)%numberOfPossibleStates]);
}
/**
* Returns this {@link Cell}'s state property.
*
* @return this {@link Cell}'s state property.
*/
public Property<CellState> getStateProperty() {
return stateProperty;
}
}
package model;
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 2018-11-29.
*/
public enum CellState {
RED(true, Color.RED), BLUE(true, Color.BLUE), DEAD(false, Color.WHITE);
public final boolean isAlive;
public final Color color;
CellState(boolean isAlive, Color color) {
this.isAlive = isAlive;
this.color = color;
}
static CellState majorityCellState(int redCount, int blueCount) {
if (redCount > blueCount)
return RED;
return BLUE;
}
}
package model;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.util.Duration;
import java.util.Random;
import static java.util.Objects.requireNonNull;
/**
* {@link GameOfLife} instances run <i>The Game of Life</i>.
*/
public class GameOfLife {
private final Random random = new Random();
private static final int PERIOD_IN_MILLISECONDS = 100;
private final Grid grid;
private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper();
private Timeline timeline;
/**
* Creates a new {@code GameOfLife} instance given the underlying {@link Grid}.
*
* @param grid the underlying {@link Grid}
* @throws NullPointerException if {@code grid} is {@code null}
*/
public GameOfLife(Grid grid) {
this.grid = requireNonNull(grid, "grid is null");
updateTimeline();
grid.randomGeneration(random);
}
private void updateTimeline() {
Duration duration = new Duration(PERIOD_IN_MILLISECONDS);
EventHandler<ActionEvent> eventHandler = event -> next();
KeyFrame keyFrame = new KeyFrame(duration, eventHandler);
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Animation.INDEFINITE);
}
/**
* Transitions into the next generationNumber.
*/
private void next() {
grid.updateToNextGeneration();
generationNumber.set(getGenerationNumber() + 1);
}
/**
* Returns the current generationNumber.
*
* @return the current generationNumber
*/
private long getGenerationNumber() {
return generationNumber.get();
}
/**
* Returns the generationNumber {@link ReadOnlyLongProperty}.
*
* @return the generationNumber {@link ReadOnlyLongProperty}
*/
public ReadOnlyLongProperty generationNumberProperty() {
return generationNumber.getReadOnlyProperty();
}
/**
* Returns the {@link Grid}.
*
* @return the {@link Grid}
*/
public Grid getGrid() {
return grid;
}
/**
* Plays the game.
*/
public void play() {
timeline.play();
}
/**
* Pauses the game.
*/
public void pause() {
timeline.pause();
}
/**
* Clears the current game.
*/
public void clear() {
pause();
grid.clear();
generationNumber.set(0);
}
/**
* Clears the current game and randomly generates a new one.
*/
public void reset() {
clear();
grid.randomGeneration(random);
}
}
package model;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
/**
* {@code Grid} instances represent the grid in <i>The Game of Life</i>.
*/
public class Grid implements Iterable<Cell> {
private final int numberOfRows;
private final int numberOfColumns;
private final Cell[][] cells;
/**
* Creates a new {@code Grid} instance given the number of rows and columns.
*
* @param numberOfRows the number of rows
* @param numberOfColumns the number of columns
* @throws IllegalArgumentException if {@code numberOfRows} or {@code numberOfColumns} are
* less than or equal to 0
*/
public Grid(int numberOfRows, int numberOfColumns) {
this.numberOfRows = numberOfRows;
this.numberOfColumns = numberOfColumns;
this.cells = createCells();
}
@Override
public Iterator<Cell> iterator() {
return new GridIterator(this);
}
private Cell[][] createCells() {
Cell[][] cells = new Cell[getNumberOfRows()][getNumberOfColumns()];
for (int rowIndex = 0; rowIndex < getNumberOfRows(); rowIndex++) {
for (int columnIndex = 0; columnIndex < getNumberOfColumns(); columnIndex++) {
cells[rowIndex][columnIndex] = new Cell();
}
}
return cells;
}
/**
* Returns the {@link Cell} at the given index.
*
* <p>Note that the index is wrapped around so that a {@link Cell} is always returned.
*
* @param rowIndex the row index of the {@link Cell}
* @param columnIndex the column index of the {@link Cell}
* @return the {@link Cell} at the given row and column index
*/
public Cell getCell(int rowIndex, int columnIndex) {
return cells[getWrappedRowIndex(rowIndex)][getWrappedColumnIndex(columnIndex)];
}
private int getWrappedRowIndex(int rowIndex) {
return (rowIndex + getNumberOfRows()) % getNumberOfRows();
}
private int getWrappedColumnIndex(int columnIndex) {
return (columnIndex + getNumberOfColumns()) % getNumberOfColumns();
}
/**
* Returns the number of rows in this {@code Grid}.
*
* @return the number of rows in this {@code Grid}
*/
public int getNumberOfRows() {
return numberOfRows;
}
/**
* Returns the number of columns in this {@code Grid}.
*
* @return the number of columns in this {@code Grid}
*/
public int getNumberOfColumns() {
return numberOfColumns;
}
/**
* Transitions all {@link Cell}s in this {@code Grid} to the next generation.
*
* <p>The following rules are applied:
* <ul>
* <li>Any live {@link Cell} with fewer than two live neighbours dies, i.e. underpopulation.</li>
* <li>Any live {@link Cell} with two or three live neighbours lives on to the next
* generation.</li>
* <li>Any live {@link Cell} with more than three live neighbours dies, i.e. overpopulation.</li>
* <li>Any dead {@link Cell} with exactly three live neighbours becomes a live cell, i.e.
* reproduction.</li>
* </ul>
*/
void updateToNextGeneration() {
goToNextState(calculateNextState());
}
private CellState[][] calculateNextState() {
CellState[][] nextCellState = new CellState[getNumberOfRows()][getNumberOfColumns()];
for (int rowIndex = 0; rowIndex < getNumberOfRows(); rowIndex++) {
for (int columnIndex = 0; columnIndex < getNumberOfColumns(); columnIndex++) {
Cell cell = getCell(rowIndex, columnIndex);
nextCellState[rowIndex][columnIndex] = calculateNextState(rowIndex, columnIndex, cell);
}
}
return nextCellState;
}
private CellState calculateNextState(int rowIndex, int columnIndex, Cell cell) {
int numberOfAliveNeighbours = countAliveNeighbors(rowIndex,columnIndex);
boolean isAliveInNextState = cellIsAliveInNextState(cell, numberOfAliveNeighbours);
int redNeighboursCount = countFilteredNeighbors(rowIndex, columnIndex, CellState.RED);
int blueNeighboursCount = countFilteredNeighbors(rowIndex, columnIndex, CellState.BLUE);
if(!cell.isAlive() && isAliveInNextState) {
return CellState.majorityCellState(redNeighboursCount, blueNeighboursCount);
}
else{
if(isAliveInNextState)
return cell.getState();
else
return CellState.DEAD;
}
}
private int countFilteredNeighbors(int rowIndex, int columnIndex, Predicate<CellState> filter) {
return (int) getNeighbors(rowIndex, columnIndex)
.stream()
.map(Cell::getState)
.filter(filter)
.count();
}
private int countFilteredNeighbors(int rowIndex, int columnIndex, CellState filteredState) {
return countFilteredNeighbors(rowIndex,columnIndex, (state)->state == filteredState);
}
public int countAliveNeighbors(int rowIndex, int columnIndex) {
return countFilteredNeighbors(rowIndex,columnIndex,(state)->state.isAlive);
}
public List<Cell> getNeighbors(int rowIndex, int columnIndex) {
int north = rowIndex - 1;
int east = columnIndex + 1;
int south = rowIndex + 1;
int west = columnIndex - 1;
return Arrays.asList(
getCell(north, west),
getCell(north, columnIndex),
getCell(north, east),
getCell(rowIndex, east),
getCell(south, east),
getCell(south, columnIndex),
getCell(south, west),
getCell(rowIndex, west)
);
}
private static boolean cellIsAliveInNextState(Cell cell, int numberOfAliveNeighbours) {
return (cell.isAlive() && numberOfAliveNeighbours == 2) || numberOfAliveNeighbours == 3;
}
private void goToNextState(CellState[][] nextState) {
for (int rowIndex = 0; rowIndex < getNumberOfRows(); rowIndex++) {
for (int columnIndex = 0; columnIndex < getNumberOfColumns(); columnIndex++) {
getCell(rowIndex, columnIndex).setState(nextState[rowIndex][columnIndex]);
}
}
}
/**
* Sets all {@link Cell}s in this {@code Grid} as dead.
*/
void clear() {
for (Cell cell : this) {
cell.setState(CellState.DEAD);
}
}
/**
* Goes through each {@link Cell} in this {@code Grid} and randomly sets it as alive or dead.
*
* @param random {@link Random} instance used to decide if each {@link Cell} is red, blue or dead
* @throws NullPointerException if {@code random} is {@code null}
*/
void randomGeneration(Random random) {
for (Cell cell : this) {
if (random.nextBoolean())
cell.setState(CellState.DEAD);
else
setCellToRandomAliveState(cell, random);
}
}
private void setCellToRandomAliveState(Cell cell, Random random) {
if (random.nextBoolean())
cell.setState(CellState.BLUE);
else
cell.setState(CellState.RED);
}
}
\ No newline at end of file
package model;
import java.util.Iterator;
/**
* {@link GridIterator} instances are used to iterate over the cells of a grid.
*/
public class GridIterator implements Iterator<Cell> {
private int rowIndex;
private int columnIndex;
private final Grid grid;
GridIterator(Grid grid) {
this.rowIndex = 0;
this.columnIndex = 0;
this.grid = grid;
}
@Override
public boolean hasNext() {
return columnIndex < grid.getNumberOfColumns() && rowIndex < grid.getNumberOfRows();
}
@Override
public Cell next() {
final Cell result = grid.getCell(rowIndex, columnIndex);
columnIndex = (columnIndex +1) % grid.getNumberOfColumns();
if(columnIndex == 0){
rowIndex++;
}
return result;
}
}
package view;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Rectangle;
import model.Cell;
import model.CellState;
import model.Grid;
/**
* Created by Arnaud Labourel on 22/11/2018.
*/
public class MatrixPane extends GridPane{
private static final double CELL_SIZE = 14;
public void initialize(Grid grid) {
for (int rowIndex = 0; rowIndex < grid.getNumberOfRows(); rowIndex++) {
for (int columnIndex = 0; columnIndex < grid.getNumberOfColumns(); columnIndex++) {
addCellRectangle(grid.getCell(rowIndex,columnIndex), rowIndex, columnIndex);
}
}
}
private void addCellRectangle(Cell cell, int rowIndex, int columnIndex) {
Rectangle rectangleCell = new Rectangle(CELL_SIZE, CELL_SIZE);
addStatePropertyListener(cell, rectangleCell);
updateFill(rectangleCell, cell.getState());
addClickEventHandler(cell, rectangleCell);
add(rectangleCell, columnIndex, rowIndex);
}
private void addStatePropertyListener(Cell cell, Rectangle cellRectangle) {
cell.getStateProperty().addListener((observable, oldValue, newValue) ->
updateFill(cellRectangle, newValue));
}
private void updateFill(Rectangle cellRectangle, CellState newCellState) {
cellRectangle.setFill(newCellState.color);
}
private void addClickEventHandler(Cell cell, Rectangle cellRectangle) {
cellRectangle.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> cell.toggleState());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.canvas.Canvas?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="Display">
<Canvas fx:id="canvas"/>
</AnchorPane>
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment