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

Revert "Correction TP"

This reverts commit bbd94e44
parent bbd94e44
No related branches found
No related tags found
1 merge request!1Revert "Correction TP"
Pipeline #1248 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 register or to comment