Java Swing: Issue painting a grid - java
The program is supposed to run a cellular automata simulation (think Conway's game of life) on a painted grid and has a start/pause button to, well, start/pause the simulation, which runs on a 1 second interval. As far as I can tell, everything else except for painting the grid (processing, rest of the GUI), works fine.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ConcurrentModificationException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CA_DriverV2 extends JFrame{
private static final Color white = Color.WHITE, black = Color.BLACK;
private Board board;
private JButton start_pause;
public CA_DriverV2(){
board = new Board();
board.setBackground(white);
start_pause = new JButton("Start");
start_pause.addActionListener(board);
this.add(board, BorderLayout.NORTH);
this.add(start_pause, BorderLayout.SOUTH);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(300, 300);
this.setVisible(true);
}
public static void main(String args[]){
new CA_DriverV2();
}
private class Board extends JPanel implements ActionListener{
private final Dimension DEFAULT_SIZE = new Dimension(5, 5);
private final int DEFAULT_CELL = 10, DEFAULT_INTERVAL = 1000, DEFAULT_RATIO = 60;
private Dimension board_size;
private int cell_size, interval, fill_ratio;
private boolean run;
private Timer timer;
private Color[][] grid;
public Board(){
board_size = DEFAULT_SIZE;
cell_size = DEFAULT_CELL;
interval = DEFAULT_INTERVAL;
fill_ratio = DEFAULT_RATIO;
run = false;
//Initialize grid with random values
//NOTE: Add JOptionPane for option to define fill rate and board size?
//ALT: Have a resize(int h, int w) method to resize grid when needed.
//ALT: Have refill(int r) method to restart with different fill ratio.
grid = new Color[board_size.height][board_size.width];
for (int h = 0; h < board_size.height; h++)
for (int w = 0; w < board_size.width; w++){
int r = (int)(Math.random() * 100);
if (r >= fill_ratio)
grid[h][w] = black;
else grid[h][w] = white;
}
timer = new Timer(interval, this);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(board_size.height, board_size.width);
}
#Override
public void paintComponent(Graphics g){
for (int h = 0; h < board_size.height; h++)
for (int w = 0; w < board_size.width; w++){
try{
if (grid[h][w] == black)
g.setColor(black);
else g.setColor(white);
g.fillRect(h * cell_size, w * cell_size, cell_size, cell_size);
} catch (ConcurrentModificationException cme){}
}
}
public void actionPerformed(ActionEvent e) {
//Timer tick processing
if (e.getSource().equals(timer)){
repaint();
Color[][] newGrid = new Color[board_size.height][board_size.width];
for (int h = 1; h < board_size.height; h++)
for (int w = 1; w < board_size.height; w++) {
int surrounding = 0;
//Count black neighbors
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++){
if(i != 0 && j != 0){
try{
if(grid[h + i][w + j] == black)
surrounding++;
} catch(ArrayIndexOutOfBoundsException ae){}
}
}
//Generate next iteration
if (surrounding > 5 || surrounding < 2)
newGrid[h][w] = black;
else newGrid[h][w] = white;
}
for (int h = 1; h < board_size.height; h++){
for (int w = 1; w < board_size.height; w++){
grid[h][w] = newGrid[h][w];
System.out.print(grid[h][w] + " ");
}
System.out.println();
}
System.out.println();
}
//Start-Pause button processing
else if(e.getSource().equals(start_pause)){
if(run){
timer.stop();
start_pause.setText("Pause");
}
else {
timer.restart();
start_pause.setText("Start");
}
run = !run;
}
}
}
}
It prints something at the very top, which looks like a sliver of the initial grid overlayed by a sliver of the button, and the rest is the default grey.
Your board Board variable is added BorderLayout.NORTH not BorderLayout.CENTER, so it only fills the top 5 pixels.
And as per my comment, you should never have code like this in your program:
catch(ArrayIndexOutOfBoundsException ae){}
Not only should you not ignore exceptions, but you shouldn't even catch this type of exceptions. Instead create your for loops with a little care so that they can handle the edges.
Also, don't forget to call the super.paintComponent(g) method in your class's override.
Related
Can anyone offer some help/advice on how to correctly create an animation?
So I'm creating the game of life in java but I'm having trouble with the animation part. I have the cells drawn on a JComponent which is displaying as it should but I have a start button that should start the whole animation process but nothing happens when I click the start button. From the tutorials I have watched and research I've done I know you must have an ActionListener that listens on the button and an actionPerformed() method that holds the code to start the animation. this being said my code is as follows: import javax.swing.JFrame; import java.util.Random; import java.util.Arrays; import javax.swing.JComponent; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Color; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.*; import javax.swing.*; import java.awt.BorderLayout; public class GameOfLife extends JFrame { int PIXELSIZE = 10; int ROW = 75; int COLUMN = 75; Random random = new Random(); JButton start; public GameOfLife() { JPanel panel = new JPanel(); DrawCells cellsComp = new DrawCells(); DrawCells buttonListener = new DrawCells(); start = new JButton("Start"); start.addActionListener(cellsComp); panel.setLayout(new BorderLayout()); start.setToolTipText("Click to start game of life"); this.setTitle("Game Of Life: Java"); this.setSize(PIXELSIZE * ROW, PIXELSIZE * COLUMN); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); panel.add(start, BorderLayout.SOUTH); panel.add(cellsComp, BorderLayout.CENTER); this.add(panel); this.setVisible(true); } private class DrawCells extends JComponent implements ActionListener { int x; int y; int grid[][] = new int[ROW][COLUMN]; int updatedGrid[][] = new int[ROW][COLUMN]; public void createGrid() { for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[i].length; j++) { grid[i][j] = random.nextInt(2); } } } public void applyRules() { for (int i = 1; i < ROW - 1; i++) { for (int j = 1; j < COLUMN - 1; j++) { int neighboursCount = 0; // used to count the neighbours of each cell neighboursCount += grid[i-1][j-1]; // top left neighboursCount += grid[i][j-1]; // top center neighboursCount += grid[i+1][j-1]; // top right neighboursCount += grid[i-1][j]; // middle left neighboursCount += grid[i+1][j]; // middle right neighboursCount += grid[i-1][j+1]; // top left neighboursCount += grid[i][j+1]; // top center neighboursCount += grid[i+1][j+1]; // top right // Game of Life rules: // Alive cells: if (grid[i][j] == 1) { // rule 1 any live cell with fewer than two live neighboours dies, as if by underpopulation if (neighboursCount < 2) { updatedGrid[i][j] = 0; } // rule 2 any live cell with two or three live neighbours, lives on to the generation else if (neighboursCount == 2 || neighboursCount == 3) { updatedGrid[i][j] = 1; } // rule 3 any live cell with more than three live neighbours dies, as if by overpopulation else if (neighboursCount > 3 && neighboursCount <= 8) { updatedGrid[i][j] = 0; } else { updatedGrid[i][j] = 0; } } // Dead cells else if (grid[i][j] == 0) { // rule 4 any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction if (neighboursCount == 3) { updatedGrid[i][j] = 1; } else { updatedGrid[i][j] = 0; } } } } for (int i = 0; i < ROW; i++) { for (int j = 0; j < COLUMN; j++) { grid[i][j] = updatedGrid[i][j]; } } } public void paintComponent(Graphics g) { super.paintComponent(g); createGrid(); Graphics2D g2 = (Graphics2D) g; for (int i = 0; i < ROW; i++) { for (int j = 0; j < COLUMN; j++) { if (grid[i][j] == 1) { g2.setColor(Color.RED); g2.fillRect(i * PIXELSIZE, j * PIXELSIZE, PIXELSIZE, PIXELSIZE); } } } } public void actionPerformed(ActionEvent e) { if (e.getSource() == start) { applyRules(); repaint(); thread.sleep(); } } } public static void main(String[] args) { GameOfLife gol = new GameOfLife(); } } What I'm actually asking for is a clear explanation on how to animate some code or a nice point in the right direction in what I'm missing/need to add in order to get my code animated. Thanks in advance for the help :D
I'm going to pretend that your gui works. In your action performed you need to start the animation. A common way to do an animation in swing is to use a Timer. Timer animation; public void actionPerformed(ActionEvent e) { if (e.getSource() == start && animation == null) { createGrid(); //remove this from paint component. int delay = 1000; //milliseconds ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { applyRules(); repaint(); } }; animation = new Timer(delay, taskPerformer); animation.start(); } } I used the anonymous class taskPerformer because that is from the example in the javadoc link provided.
How to repaint image for every variable change from JSlider?
I want to make the displayed image repainted for everytime i change the slider position. I've already made the Every change of the Variable from JSlider is added to the pixel. But i just don't know how to repaint it. package training; import javax.swing.*; import java.io.*; import java.awt.*; import java.awt.image.*; import javax.imageio.*; import javax.swing.plaf.SliderUI; import java.awt.Color; import java.util.Arrays; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class Training extends JPanel { public BufferedImage image; double maxw, maxh; double w, h, ratio; int warna, red, green, blue, abu, value; int forT1, forT2; int[][] bmpR; int[][] bmpG; int[][] bmpB; int[][] alpha; public Training () { super(); try { image = ImageIO.read(new File("src/training/V.jpg")); } catch (IOException e) { //Not handled. } maxw = 750; maxh = 600; w = image.getWidth(); h = image.getHeight(); bmpR = new int[(int)w][(int)h]; bmpG = new int[(int)w][(int)h]; bmpB = new int[(int)w][(int)h]; if (w > h) { if (w > maxw) { ratio = maxw / w; h = h * ratio; // Reset height to match scaled image w = w * ratio; } } if (w <= h) { if (h > maxh) { ratio = maxh / h; w = w * ratio; // Reset height to match scaled image h = h * ratio; } } try { for( int i = 0; i < w; i++ ) { for( int j = 0; j < h; j++ ) { Color c = new Color(image.getRGB(i, j)); bmpR [i][j] = c.getRed(); bmpG [i][j] = c.getGreen(); bmpB [i][j] = c.getBlue(); // alpha = c.getAlpha(); } } System.out.println(bmpB[40][40]); } catch (Exception e) { System.out.println("Terjadi kesalahan saat mengambil data pixel"); e.printStackTrace(); return; } } public void paintComponent(Graphics g) { super.paintComponent(g); Image i = image.getScaledInstance((int)w, (int)h,Image.SCALE_SMOOTH); g.drawImage(i, 20, 20, null); } public static void main(String[] args) { final Training ns = new Training(); System.out.println("User dir: " + System.getProperty("user.dir")); JFrame f = new JFrame("Window"); JPanel p = new Training(); f.setSize(1100, 600); p.setSize(750, 600); f.add(p); JSlider Temp = new JSlider(-50, 50, 0); Temp.setMajorTickSpacing(10); Temp.setMinorTickSpacing(1); Temp.addChangeListener(new ChangeListener () { public void stateChanged(ChangeEvent evt) { JSlider Temp = (JSlider) evt.getSource(); if (Temp.getValueIsAdjusting()) { ns.value = Temp.getValue(); for(ns.forT1 = 0; ns.forT1 < ns.w; ns.forT1++ ) { for(ns.forT2 = 0; ns.forT2 < ns.h; ns.forT2++ ) { ns.bmpB[ns.forT1][ns.forT2] = ns.bmpB[ns.forT1][ns.forT2] - ns.value; if (ns.bmpB[ns.forT1][ns.forT2] > 255) { ns.bmpB[ns.forT1][ns.forT2] = 255; } if (ns.bmpB[ns.forT1][ns.forT2] < 0) { ns.bmpB[ns.forT1][ns.forT2] = 0; } ns.bmpR[ns.forT1][ns.forT2] = ns.bmpR[ns.forT1][ns.forT2] + ns.value; if (ns.bmpR[ns.forT1][ns.forT2] > 255) { ns.bmpR[ns.forT1][ns.forT2] = 255; } if (ns.bmpR[ns.forT1][ns.forT2] < 0) { ns.bmpR[ns.forT1][ns.forT2] = 0; } } } } ns.repaint(); } }); f.add(Temp, BorderLayout.EAST); f.setVisible(true); } } Did i misplaced the ChangeListener or should i put paintComponent method after the change listener happens?
The random indentation of your code is making it hard to figure out exactly what's going on, but I don't see repaint() anywhere inside your ChangeListener. You need to use repaint() to trigger the repainting of your component.
Why won't gc.clearRect clear the canvas?
I have some code in a MazeUI class that creates a couple of fields in JavaFX for entering the height and width of a Maze to be generated along with a Button and the event for the button. On clicking Generate Maze the code should generate a random maze. Now this works fine. But the line to clear the canvas after the Maze is first drawn using gc.clearRect(x, y, z, a) doesn't appear to work and Maze's are re-drawn on top of one another on subsequent clicks: package dojo.maze.ui; import dojo.maze.generator.MazeGenerator; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.effect.BoxBlur; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.StrokeLineCap; import javafx.scene.shape.StrokeLineJoin; import javafx.stage.Stage; public class MazeUI extends Application { private MazeGenerator generator; private Integer height = 15; private Integer width = 15; #Override public void start(Stage primaryStage) throws Exception { primaryStage.setTitle("Dojo: Solving a Maze"); Group root = new Group(); drawMazeView(root); primaryStage.setScene(new Scene(root, Color.WHITE)); primaryStage.show(); } private GraphicsContext initialiseGraphicsContext(Canvas canvas) { GraphicsContext gc = canvas.getGraphicsContext2D(); gc.setFill(Color.BLACK); gc.fillRect(0,0,600,600); gc.setStroke(Color.GREEN); gc.setLineCap( StrokeLineCap.ROUND ); gc.setLineJoin( StrokeLineJoin.ROUND ); gc.setLineWidth(3); BoxBlur blur = new BoxBlur(); blur.setWidth(1); blur.setHeight(1); blur.setIterations(1); gc.setEffect(blur); return gc; } private void drawMazeView(Group root) { Canvas canvas = new Canvas(800, 800); GraphicsContext gc = initialiseGraphicsContext(canvas); GridPane.setConstraints(canvas, 0, 6); GridPane grid = new GridPane(); grid.setPadding(new Insets(10, 10, 10, 10)); grid.setVgap(5); grid.setHgap(5); Label heightLabel = new Label("Height:"); final TextField heightTextField = new TextField(); HBox hbHeight = new HBox(); hbHeight.getChildren().addAll(heightLabel, heightTextField); hbHeight.setSpacing(10); GridPane.setConstraints(hbHeight, 0, 0); Label widthLabel = new Label("Label:"); final TextField widthTextField = new TextField(); HBox hbWidth = new HBox(); hbWidth.getChildren().addAll(widthLabel, widthTextField); hbWidth.setSpacing(10); GridPane.setConstraints(hbWidth, 0, 2); VBox fieldsBox = new VBox(); fieldsBox.getChildren().addAll(hbHeight, hbWidth); // Create button that allows you to generate a new maze Button btn = new Button(); btn.setText("Generate Random Maze"); btn.setOnAction(new EventHandler<ActionEvent>() { #Override public void handle(ActionEvent event) { System.out.println("Button clicked!"); height = Integer.valueOf(heightTextField.getText()); width = Integer.valueOf(widthTextField.getText()); // clear old maze gc.clearRect(0, 0, canvas.getHeight(), canvas.getWidth()); generator = new MazeGenerator(height, width); drawMaze(gc); } }); GridPane.setConstraints(btn, 0, 4); grid.getChildren().addAll(fieldsBox, btn, canvas); root.getChildren().add(grid); } void drawMaze(GraphicsContext gc) { int[][] maze = generator.maze(); int xPos = 20, yPos = 20, length = 40, gap = 10; for (int i = 0; i < width; i++) { xPos = 20; // draw the north edge for (int j = 0; j < height; j++) { if ((maze[j][i] & 1) == 0) { gc.strokeLine(xPos, yPos, xPos + length, yPos); // horizontal } xPos += length + gap; System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ "); } System.out.println("+"); xPos = 20; // draw the west edge for (int j = 0; j < height; j++) { if ((maze[j][i] & 8) == 0) { gc.strokeLine(xPos, yPos, xPos, yPos + length); // vertical } xPos += length + gap; System.out.print((maze[j][i] & 8) == 0 ? "| " : " "); } gc.strokeLine(xPos, yPos, xPos, yPos + length); // vertical System.out.println("|"); yPos += length + gap; } // draw the bottom line xPos = 20; // reset x pos to western edge for (int j = 0; j < height; j++) { gc.strokeLine(xPos, yPos, xPos + length, yPos); // horizontal System.out.print("+---"); xPos += length + gap; } System.out.println("+"); } public static void main(String[] args) { launch(args); } } Code for MazeGenerator: package dojo.maze.generator; import java.util.Arrays; import java.util.Collections; /* * recursive backtracking algorithm * shamelessly borrowed from the ruby at * http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking */ public class MazeGenerator { private final int x; private final int y; private final int[][] maze; public static final int[][] mazeProblemOne = new int[][] {{2,5,2,3,7,3,1,6,7,3,3,5,6,3,5},{4,10,3,5,12,6,3,9,10,3,5,12,8,6,13},{12,6,5,12,12,14,3,1,6,3,9,10,3,9,12},{12,12,12,12,12,12,6,3,9,4,6,7,1,6,9},{14,9,10,9,12,12,12,6,5,12,12,10,5,12,4},{12,2,7,5,12,12,10,9,12,10,13,4,10,9,12},{12,6,9,12,12,12,2,5,10,5,10,11,3,3,13},{12,10,5,12,10,11,3,13,4,10,5,6,3,1,12},{12,6,9,10,5,4,6,9,12,6,9,12,6,3,9},{10,9,6,1,12,10,11,3,9,12,6,13,12,2,5},{6,7,9,6,9,6,3,3,3,9,8,12,12,6,13},{8,12,6,9,6,13,6,3,7,3,3,13,12,12,12},{6,9,10,5,12,12,12,4,10,3,5,8,12,12,8},{14,3,5,12,8,12,10,11,3,5,10,5,12,10,5},{10,1,10,11,3,9,2,3,3,11,1,10,11,3,9}}; public static final int[][] mazeProblemTwo = new int[][] {{2,5,6,5,6,3,1,6,3,3,7,5,2,3,5},{4,10,9,12,14,3,3,9,6,5,12,10,3,3,9},{14,3,3,9,8,6,3,5,12,12,10,3,3,3,5},{12,6,3,3,5,12,4,10,9,10,3,3,3,3,13},{12,12,6,5,12,12,10,3,3,3,5,6,3,3,9},{12,10,9,12,10,9,6,5,6,3,13,10,3,3,5},{10,3,5,12,6,5,12,10,9,4,14,3,3,1,12},{4,6,9,12,12,10,9,6,3,11,13,6,3,3,9},{12,12,2,13,14,3,5,8,6,5,8,10,3,3,5},{12,10,3,9,12,4,12,6,9,12,6,5,6,3,9},{14,7,3,1,10,13,12,12,4,12,12,10,9,6,1},{12,10,3,7,1,12,10,11,9,12,12,2,3,11,5},{12,2,5,12,6,9,2,5,6,9,10,3,3,5,12},{10,5,12,12,12,6,3,13,12,6,7,1,6,9,12},{2,11,9,10,11,9,2,9,10,9,10,3,11,3,9}}; public static final int[][] mazeProblemThree = new int[][] {{2,5,2,3,7,3,3,3,5,6,3,1,6,7,1},{4,10,3,5,12,2,5,6,9,10,3,3,9,14,5},{10,7,5,12,10,5,14,9,6,5,6,3,5,12,12},{6,9,8,10,3,9,12,6,13,12,10,5,12,12,12},{12,6,3,7,1,6,9,12,12,10,3,9,12,8,12},{12,12,4,10,5,10,5,8,14,3,5,2,11,3,13},{12,10,13,4,10,5,10,5,10,5,10,5,6,5,12},{14,1,12,10,5,14,1,12,6,9,4,10,9,12,12},{14,5,10,5,12,10,5,12,12,2,15,3,1,12,12},{8,12,6,9,10,5,12,12,10,3,9,6,3,9,12},{6,9,14,3,3,9,12,10,3,3,3,9,4,6,9},{10,5,12,6,3,3,13,6,3,3,1,6,11,9,4},{6,9,12,10,5,6,11,9,6,3,3,9,6,3,13},{14,5,12,4,12,10,1,6,9,6,5,2,13,4,12},{8,10,11,9,10,3,3,11,3,9,10,3,9,10,9}}; public static final int[][] mazeProblemFour = new int[][] {{2,3,3,5,4,6,7,3,3,5,6,5,6,3,5},{6,3,1,12,12,12,10,3,5,10,9,12,10,5,12},{12,6,3,9,14,9,4,6,9,2,3,11,1,12,12},{14,9,2,3,11,5,12,10,3,5,6,3,3,9,12},{10,5,6,5,2,11,11,5,4,12,12,6,7,1,12},{4,10,9,10,3,5,6,9,12,10,9,8,12,6,13},{14,5,4,6,3,9,12,6,11,5,6,3,9,12,8},{12,10,9,12,4,6,9,10,5,12,14,3,5,10,5},{12,6,5,12,12,12,6,3,9,12,8,6,13,4,12},{14,9,10,9,12,12,10,3,5,10,5,12,10,13,12},{12,2,7,5,10,11,3,3,9,6,9,12,2,9,12},{10,3,9,10,3,3,5,4,6,11,3,9,6,3,13},{6,5,6,7,3,5,12,10,9,6,3,3,9,6,9},{12,10,9,10,5,8,12,6,5,10,5,6,5,10,5},{10,3,3,1,10,3,11,9,10,3,9,8,10,3,9}}; public static final int[][] mazeProblemFive = new int[][] {{2,3,5,6,3,3,7,5,6,3,3,3,7,3,5},{6,5,12,12,6,3,9,8,10,5,4,6,9,4,12},{12,12,12,12,10,3,5,6,5,10,13,10,5,14,9},{12,10,9,10,5,4,10,9,14,1,12,4,12,10,5},{10,5,6,5,10,15,3,1,14,5,14,9,10,5,8},{6,9,12,10,5,8,6,5,8,10,9,6,5,14,5},{10,3,9,4,12,6,9,10,3,3,3,9,12,8,12},{6,3,7,13,12,10,7,5,2,7,7,1,10,3,13},{14,1,12,8,10,5,12,12,6,9,12,6,3,3,9},{8,6,13,6,3,9,12,12,12,2,13,12,6,3,5},{6,9,8,12,4,6,9,12,14,5,8,10,9,4,12},{12,6,3,9,10,9,6,9,8,10,7,5,6,11,9},{12,10,3,3,3,5,14,3,3,5,12,12,10,5,4},{14,1,6,5,6,9,10,3,1,12,12,10,1,10,13},{10,3,9,10,11,3,3,3,3,9,10,3,3,3,9}}; public MazeGenerator(int x, int y) { this.x = x; this.y = y; maze = new int[this.x][this.y]; generateMaze(0, 0); } public void display() { for (int i = 0; i < y; i++) { // draw the bbc.north edge for (int j = 0; j < x; j++) { System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ "); } System.out.println("+"); // draw the west edge for (int j = 0; j < x; j++) { System.out.print((maze[j][i] & 8) == 0 ? "| " : " "); } System.out.println("|"); } // draw the bottom line for (int j = 0; j < x; j++) { System.out.print("+---"); } System.out.println("+"); } private void generateMaze(int cx, int cy) { DIR[] dirs = DIR.values(); Collections.shuffle(Arrays.asList(dirs)); for (DIR dir : dirs) { int nx = cx + dir.dx; int ny = cy + dir.dy; if (between(nx, x) && between(ny, y) && (maze[nx][ny] == 0)) { maze[cx][cy] |= dir.bit; maze[nx][ny] |= dir.opposite.bit; generateMaze(nx, ny); } } } private static boolean between(int v, int upper) { return (v >= 0) && (v < upper); } public int[][] maze() { return maze; } private enum DIR { N(1, 0, -1), S(2, 0, 1), E(4, 1, 0), W(8, -1, 0); private final int bit; private final int dx; private final int dy; private DIR opposite; // use the static initializer to resolve forward references static { N.opposite = S; S.opposite = N; E.opposite = W; W.opposite = E; } private DIR(int bit, int dx, int dy) { this.bit = bit; this.dx = dx; this.dy = dy; } }; public static void main(String[] args) { int x = args.length >= 1 ? (Integer.parseInt(args[0])) : 8; int y = args.length == 2 ? (Integer.parseInt(args[1])) : 8; MazeGenerator maze = new MazeGenerator(x, y); maze.display(); } } How do I fix the code so that it correctly clears the Maze after each button click? Am I missing something?
Remove the BoxBlur effect before you clear the canvas, then re-apply it. Clearing the canvas simply paints with a transparent color. So the BoxBlur effect will affect that too. And what jewelsea said. You'd have found it yourself if you'd only reduced the code to a minimum ;-)
For people looking for an answer, another reason why it may not be working is if you set the GraphicsContext.globalBlendMode to something like BlendMode.SCREEN. Since clearRect() paints the canvas with transparent pixels, a transparent pixel would have no effect in that BlendMode. Set the gc.globalBlendMode = BlendMode.SRC_OVER right before calling clearRect()
Determine if circles intersect
I am working on a project where I have to draw 20 circles with random starting points and random sizes. Then I have to determine if any of the circles intersect. If a circle intersects with another, I have to color that circle green. And if the circle does not intersect with another, the color needs to be red. I have all of the code... I think... but when I run it, I still get some circles that should be green, but are red instead. Here is my code. Any help will be greatly appreciated. import java.awt.Graphics; import javax.swing.JPanel; import java.util.Random; import javax.swing.JFrame; import java.awt.*; public class IntersectingCircles extends JPanel { private int[] xAxis = new int [20]; // array to hold x axis points private int[] yAxis = new int [20]; // array to hold y axis points private int[] radius = new int [20]; // array to hold radius length public static void main (String[] args) { JFrame frame = new JFrame("Random Circles"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); frame.getContentPane().add (new IntersectingCircles()); frame.pack(); frame.setVisible(true); } public IntersectingCircles() { setPreferredSize(new Dimension(1300, 800)); // set window size Random random = new Random(); for (int i = 0; i < 20; i++) { xAxis[i] = random.nextInt(800) + 100; yAxis[i] = random.nextInt(500) + 100; radius[i] = random.nextInt(75) + 10; } } public void paintComponent(Graphics g) { for (int i = 0; i < 20; i++) { int color = 0; for (int h = 0; h < 20; h++) { if(i < h) { double x1 = 0, x2 = 0, y1 = 0, y2 = 0, d = 0; x1 = (xAxis[i] + radius[i]); y1 = (yAxis[i] + radius[i]); x2 = (xAxis[h] + radius[h]); y2 = (yAxis[h] + radius[h]); d = (Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1)*(y2 - y1)))); if (d > radius[i] + radius[h] || d < (Math.abs(radius[i] - radius[h]))) { color = 0; } else { color = 1; break; } } } if (color == 0) { g.setColor(Color.RED); g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2); } else { g.setColor(Color.GREEN); g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2); } } } }
In the inside for loop, you are only comparing circles of i index with circles with h index, but only those with i < h, because of the condition: for (int h = 0; h < 20; h++) { if(i < h) { ... So, instead you should compare every i circle with every h circle, except if they are the same. You want instead: for (int h = 0; h < 20; h++) { if(i != h) //note the change here { ...
Java draw stairs using drawRect and using inputField for more stairs
I'm a beginner whit Java experience so I hope you can help me. I want to read the number of steps from a JTextfield. But how can you make the stairs variable? Graphics g = textP.getGraphics(); int x = 5; int y = 20; int width = 10; int height = 10; For loop 1 - whil give a drawRect of 6 pieces for (int i = 0; i < 6; i++) { g.drawRect(x, y * i, width, height); } For loop 2 - whil give a drawRect of 5 pieces for (int i = 1; i < 6; i++) { g.drawRect(x + 15, y * i, width, height); } For loop 3 - whil give a drawRect of 4 pieces for (int i = 2; i < 6; i++) { g.drawRect(x + 30, y * i, width, height); } For loop 4 - whil give a drawRect of 3 pieces for (int i = 3; i < 6; i++) { g.drawRect(x + 45, y * i, width, height); } For loop 5 - whil give a drawRect of 2 pieces for (int i = 4; i < 6; i++) { g.drawRect(x + 60, y * i, width, height); } For loop 6 - whil give a drawRect of 1 pieces for (int i = 5; i < 6; i++) { g.drawRect(x + 75, y * i, width, height); } Output (must by an rect ipv *): * ** *** **** ***** ******
You can do it this way. JTextField stairs = new JTextField("Enter no. of Stairs"); String noOfStairsStr = stairs.getText(); int noOfStairs = Integer.parseInt(noOfStairsStr); ... for (int i = 0; i < noOfStairs; i++) { // Use that in the for loop.
Are you expecting something like this for (int i = 0,k=15; i < 6; i++) { g.drawRect( ( x+(i*k) ), y * i, width, height); }
A Graphic environment is complex thing. No longer do you have the safety of fixed character width and heights, now you need to start dealing with a wider range of environmental factors (such as the width and height of the area you have to paint in...) To get start I would suggest you take a look at Creating a GUI with Swing Performing custom painting 2D Graphics To cover the basics. In order to paint steps, we need to know (at least) three things. The number of steps to be painted... The width of each step The height of each step. This example calculates the width and height of the steps as a factor of the width and height of the container it's painting on. import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class SimpleSteps { public static void main(String[] args) { new SimpleSteps(); } public SimpleSteps() { EventQueue.invokeLater(new Runnable() { #Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private JTextField steps; private StairPane stairPane; public TestPane() { setLayout(new BorderLayout()); JPanel options = new JPanel(); steps = new JTextField(10); JButton create = new JButton("Create"); stairPane = new StairPane(); options.add(new JLabel("Step count: ")); options.add(steps); options.add(create); add(stairPane); add(options, BorderLayout.SOUTH); create.addActionListener(new ActionListener() { #Override public void actionPerformed(ActionEvent e) { String value = steps.getText(); try { int stepCount = Integer.parseInt(value); stairPane.setStepCount(stepCount); } catch (NumberFormatException exp) { JOptionPane.showMessageDialog(TestPane.this, value + " is not a valid step count", "Error", JOptionPane.ERROR_MESSAGE); } } }); } } public class StairPane extends JPanel { private int stepCount = 0; public StairPane() { } #Override public Dimension getPreferredSize() { return new Dimension(200, 200); } #Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (stepCount > 0) { Graphics g2d = (Graphics2D) g.create(); int stepHeight = getHeight() / stepCount; int stepWidth = getWidth() / stepCount; for (int step = stepCount; step != 0; step--) { int width = stepWidth * step; int y = (stepHeight * step) - stepHeight; g2d.fillRect(0, y, width, stepHeight); } g2d.dispose(); } } private void setStepCount(int stepCount) { this.stepCount = stepCount; repaint(); } } }