http://www.youtube.com/watch?v=M0cNsmjK33E
I want to develop something similar to the link above using Java Swing. I have the sorting method and did while repaint but when I triggered the sorting, instead of showing the bars slowly sorting itself, it freezes and then unfreezes when the array has been fully sorted.
How do I fix this?
Edit: sorry forgot about the codes. its a very simple gui. and another class for sorting which sorts the whole array
public class SortGUI {
JFrame frame;
int frameWidth = 1000, frameHeight = 1000;
int panelWidth, panelHeight;
DrawPanel panel;
JPanel panel2;
JScrollPane scroll;
JViewport view;
static int[] S = new int[50000];
public static void main(String[] args) throws InterruptedException {
SortGUI app = new SortGUI();
initializeArray();
app.go();
}
public static void initializeArray()
{
for (int i = 0; i < S.length; i++) {
S[i] = (int) (Math.random() * 16581375);
}
}
public void go() throws InterruptedException {
//Frame
frame = new JFrame();
frame.setSize(frameWidth, frameHeight);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//panel
panel = new DrawPanel();
scroll = new JScrollPane(panel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
//Layout
frame.add(scroll);
frame.addKeyListener(new keyListener());
while(true)
{
panel.repaint();
}
}
public class DrawPanel extends JPanel
{
public DrawPanel()
{
this.setPreferredSize(new Dimension(50000,930));
}
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
for(int i = 0; i < S.length; i++)
{
int red = S[i] / 65025;
int green = (S[i] > 65025)? S[i] % 65025 : 0;
int blue = green;
blue %= 255;
green /= 255;
g.setColor(new Color(red,green,blue));
g.fillRect(i, 900 - (S[i] / 18500), 1, S[i] / 18500);
}
}
}
public class keyListener implements KeyListener{
public void keyTyped(KeyEvent ke) {
}
public void keyPressed(KeyEvent ke) {
if(ke.getKeyChar() == '1')
{
sorter.bubbleSort(S);
}
}
public void keyReleased(KeyEvent ke) {
}
}
}
Note: I started writing this before the question was deleted
Most likely your using some looping mechanism and praying that each iteration, the ui with be updated. That's a wrong assumption. The UI will not be update until the loop is finished. What you are doing is what we refer to as blocking the Event Dispatch Thread(EDT)
See How to use a Swing Timer. Make "iterative" updates in the ActionListener call back. For instance, if you want to animate a sorting algorithm, you need to determine what needs to be updated per "iteration" of the timer callback. Then each iteration repaint the ui.
So your Timer timer could look something like
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if (sortingIsDone()) {
((Timer)e.getSource()).stop();
} else {
sortOnlyOneItem();
}
repaint();
}
});
Your sortOnlyOneItem method should only, well, perform a sort for just one item. And have some sort of flag to check if the sorting is done, then stop the timer.
Other notes:
You should be calling super.paintComponent in the paintComponent method, if you aren't going to paint the background yourself. Generally I always do though.
Here's a complete example. I'm glad you figured it out on your own. I was working on this example before I saw that you got it.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SelectionSortAnimate extends JPanel {
private static final int NUM_OF_ITEMS = 20;
private static final int DIM_W = 400;
private static final int DIM_H = 400;
private static final int HORIZON = 350;
private static final int VERT_INC = 15;
private static final int HOR_INC = DIM_W / NUM_OF_ITEMS;
private JButton startButton;
private Timer timer = null;
private JButton resetButton;
Integer[] list;
int currentIndex = NUM_OF_ITEMS - 1;
public SelectionSortAnimate() {
list = initList();
timer = new Timer(200, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isSortingDone()) {
((Timer) e.getSource()).stop();
startButton.setEnabled(false);
} else {
sortOnlyOneItem();
}
repaint();
}
});
startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
resetButton = new JButton("Reset");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
list = initList();
currentIndex = NUM_OF_ITEMS - 1;
repaint();
startButton.setEnabled(true);
}
});
add(startButton);
add(resetButton);
}
public boolean isSortingDone() {
return currentIndex == 0;
}
public Integer[] initList() {
Integer[] nums = new Integer[NUM_OF_ITEMS];
for (int i = 1; i <= nums.length; i++) {
nums[i - 1] = i;
}
Collections.shuffle(Arrays.asList(nums));
return nums;
}
public void drawItem(Graphics g, int item, int index) {
int height = item * VERT_INC;
int y = HORIZON - height;
int x = index * HOR_INC;
g.fillRect(x, y, HOR_INC, height);
}
public void sortOnlyOneItem() {
int currentMax = list[0];
int currentMaxIndex = 0;
for (int j = 1; j <= currentIndex; j++) {
if (currentMax < list[j]) {
currentMax = list[j];
currentMaxIndex = j;
}
}
if (currentMaxIndex != currentIndex) {
list[currentMaxIndex] = list[currentIndex];
list[currentIndex] = currentMax;
}
currentIndex--;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < list.length; i++) {
drawItem(g, list[i], i);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(DIM_W, DIM_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Sort");
frame.add(new SelectionSortAnimate());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Related
I don't really understand why this program draws three pawns instead of one and two of which seem to have a random(probably not so random) positions. enter image description here
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GamePanel extends JPanel implements MouseListener {
static final int SCREEN_EDGE = 800;
static final int GAME_UNITS = 64;
static final int UNIT_SIZE = 100;
final int[] x = new int[GAME_UNITS];
final int[] y = new int[GAME_UNITS];
boolean running = false;
public GamePanel() {
this.setPreferredSize(new Dimension(SCREEN_EDGE, SCREEN_EDGE));
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
int[] position = {0,0};
int[] position1 = {1, 0};
new Pawn(position,-1);
}
private void startGame() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g){
int counter = 1;
for (int y = 0; y < SCREEN_EDGE/UNIT_SIZE; y++) {
// 1 == "white" 2 == "black"
int color = (y % 2 == 0) ? 1 : 2;
for (int x = 0; x < SCREEN_EDGE/UNIT_SIZE; x++) {
g.setColor(color == 1 ? new Color(239,217, 181) : new Color(180, 136,98));
g.fillRect(x*UNIT_SIZE, y*UNIT_SIZE, UNIT_SIZE, UNIT_SIZE);
color = color == 1 ? 2 : 1;
}
}
for (int i = 0; i < Figure.figures.length; i++) {
JLabel figureSprite = new JLabel(Figure.figures[i].image, JLabel.CENTER);
figureSprite.setSize(90,90);
figureSprite.setLocation(Figure.figures[i].position[0] + 5,Figure.figures[i].position[1] + 5);
this.add(figureSprite);
}
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
public class MyKeyAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
}
}
}
import javax.swing.*;
public abstract class Figure{
protected int value;
protected ImageIcon image;
protected int[][] possibleMoves;
public int[] position;
// white = -1 black = 1
protected int whiteOrBlack;
protected static int figureCount = 1;
// int[figureCount][0 = x][1 = y][2 = color]
public static Figure[] figures = new Figure[figureCount];
public Figure(int value, int[] position, int[][] possibleMoves , int whiteOrBlack) {
this.value = value;
this.position = position;
this.possibleMoves = possibleMoves;
this.whiteOrBlack = whiteOrBlack;
Figure[] oldFigures = figures;
figures = new Figure[figureCount];
for (int i = 0; i < oldFigures.length; i++) {
figures[i] = oldFigures[i];
}
figures[figureCount - 1] = this;
figureCount++;
}
public abstract void move(int[] coordinates);
}
import javax.swing.*;
import java.awt.*;
import java.io.*;
public class Pawn extends Figure{
public Pawn(int[] position, int whiteOrBlack) {
super(1, position, new int[3][2], whiteOrBlack);
super.image = new ImageIcon(getClass().getClassLoader().getResource("graphics/" + (whiteOrBlack == -1 ? "whitePawn.png" : "blackPawn.png")));
Image newImage = super.image.getImage().getScaledInstance(90,90, Image.SCALE_AREA_AVERAGING);
super.image = new ImageIcon(newImage);
}
public void checkMoves(){
for (int i = 0; i < figures.length; i++) {
if((position[0] - 1) == figures[i].position[0] && (position[1] + this.whiteOrBlack) == figures[i].position[1] && figures[i].whiteOrBlack != this.whiteOrBlack) {
possibleMoves[0][0] = position[0] - 1;
possibleMoves[0][1] = position[1] + this.whiteOrBlack;
}else possibleMoves[0] = new int[2];
if((position[0]) != figures[i].position[0] && (position[1]) != figures[i].position[1]){
possibleMoves[1][0] = position[0];
possibleMoves[1][1] = position[1] + 1;
}else possibleMoves[1] = new int[2];
if((position[0] + 1) == figures[i].position[0] && (position[1] + this.whiteOrBlack) == figures[i].position[1] && figures[i].whiteOrBlack != this.whiteOrBlack) {
possibleMoves[2][0] = position[0] + 1;
possibleMoves[2][1] = position[1] + this.whiteOrBlack;
}else possibleMoves[2] = new int[2];
}
}
#Override
public void move(int[] coordinates) {
}
}
import javax.swing.*;
public class GameFrame extends JFrame {
public GameFrame(){
this.add(new GamePanel());
this.setTitle("Chess");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setResizable(false);
this.setVisible(true);
this.setLocationRelativeTo(null);
}
}
public class ChessGame {
public static void main(String[] args) {
new GameFrame();
}
}
I tried few thing like changing JLabel to BufferedImage but it would've generate other problems down the line like not being able to use MouseListener so i feel stuck. I would love to know why this code generates 3 textures too.
It looks like you are adding FigureSprites from within the drawComponent() method. The more often you draw the window, the more figures you have to draw.
Instead within drawComponent() just draw the current state but do not modify it. Adding figures has to come from somewhere else. For example, you could create the necessary pawns in the constructor. Or in extra methods that might get triggered based on user input.
In case you modify the GamePanel's state enough so that it should get painted freshly, just invoke repaint(). Swing will mark this component for repainting and decide on it's own when to run the paint() method, which in turn will run paintComponent().
I have been making a sorting algorithm visualizer in Java using Java Swing and AWT and coded insertion sort to see if it would be able to work. The algorithm works in the sense that when this program is run you can shuffle and sort the algorithm using insertion short but you don't actually see the algorithm in action. It just happens instantly and have been looking for ways to add some sort of delay but I can't find any sources to help me.
I set it up with 4 java classes, the main which just init's the window, the window class, array visualizer class, and the insertion sort class.
Window.java:
public class Window implements ActionListener {
//Window width
protected static int WINDOW_WIDTH = 1980;
//Window height
protected static int WINDOW_HEIGHT = 1080;
private int delay = 100;
//This will draw all our rectangles
protected static ArrayVisualizer arrayVisualizer;
//Make a new JFrame
JFrame window = new JFrame();
JButton shuffleBut = new JButton("Shuffle");
JButton startSort = new JButton("Start Sorting");
public Window() {
initWindow();
}
private void addButtons() {
//Shuffle Button
shuffleBut.setBounds(100, 50, 100, 100);
shuffleBut.setBackground(Color.white);
shuffleBut.addActionListener(this);
startSort.setBounds(500, 50, 100, 100);;
startSort.setBackground(Color.white);
startSort.addActionListener(taskPerformer);
window.add(shuffleBut);
window.add(startSort);
}
private void initWindow() {
ImageIcon logo = new ImageIcon();
window = new JFrame();
window.setTitle("JAlgorithms");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
window.setLocationRelativeTo(null);
window.setResizable(false);
addButtons();
arrayVisualizer = new ArrayVisualizer();
window.add(arrayVisualizer);
arrayVisualizer.repaint(); //Will call paint component method
window.pack();
window.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == shuffleBut) {
arrayVisualizer.shuffle(ArrayVisualizer.array);
arrayVisualizer.repaint();
}
}
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent event) {
if(event.getSource() == startSort) {
arrayVisualizer.sort(ArrayVisualizer.array);
arrayVisualizer.repaint();
}
}
};
}
ArrayVisualizer.java:
public class ArrayVisualizer extends JPanel {
protected static int[] array;
private final int REC_WIDTH = 1; //1980 rectangles
private final int NUMBER_OF_RECS = Window.WINDOW_WIDTH / REC_WIDTH;
public ArrayVisualizer() {
array = new int[NUMBER_OF_RECS];
generateRandom(array);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g.create();
graphics.setColor(Color.orange);
for(int i = 0; i < NUMBER_OF_RECS; i++) {
int height = array[i] * 4; //Done for scaling
int recX = i + (REC_WIDTH - 1) * i; //Read fillRect documentation
int recY = Window.WINDOW_HEIGHT - height; //Read fillRect documentation
graphics.fillRect(recX, recY, REC_WIDTH, height);
}
}
//This will return the Dimension of the actual rectangles. i.e the rectangles will only exist when this exists, almost like a canvas in javascript
#Override
public Dimension getPreferredSize() {
return new Dimension(Window.WINDOW_WIDTH, Window.WINDOW_HEIGHT);
}
//Creates a random unsorted array with numbers 1-200
protected void generateRandom(int[] array) {
Random number = new Random();
for(int i = 0; i < NUMBER_OF_RECS; i++) {
array[i] = number.nextInt(200);
}
}
protected void shuffle(int[] array) {
generateRandom(array);
}
protected void sort(int[] array) {
InsertionSort.insertionSort(array);
}
}
InsertionSort.java:
public class InsertionSort {
public static void insertionSort(int arr[])
{
int n = arr.length;
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
}
UPDATE (Here is the modified code, I added selection sort as well and heavily modified the suggestion I checkmarked):
Main.java:
public class Main {
public static void main(String[] args) {
//Opens window
Window window = new Window();
}
}
Window.java:
import java.awt.Color;
import java.awt.Image;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.EventQueue;
import javax.swing.ImageIcon;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Window implements ActionListener {
//Window width
protected static int WINDOW_WIDTH = 1440;
//Window height
protected static int WINDOW_HEIGHT = 1080;
//This will draw all our rectangles
protected static ArrayVisualizer arrayVisualizer;
//Make a new JFrame
JFrame window = new JFrame();
JButton shuffleBut = new JButton("Shuffle");
JButton startSort = new JButton("Start Sorting");
public Window() {
initWindow();
}
private void addButtons() {
//Shuffle Button
shuffleBut.setBounds(100, 50, 100, 100);
shuffleBut.setBackground(Color.white);
shuffleBut.addActionListener(this);
startSort.setBounds(500, 50, 100, 100);;
startSort.setBackground(Color.white);
window.add(shuffleBut);
window.add(startSort);
}
private void initWindow() {
ImageIcon logo = new ImageIcon();
window = new JFrame();
window.setTitle("JAlgorithms");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
window.setLocationRelativeTo(null);
window.setResizable(false);
addButtons();
startSort.addActionListener(taskPerformer);
arrayVisualizer = new ArrayVisualizer();
window.add(arrayVisualizer);
arrayVisualizer.repaint(); //Will call paint component method
window.pack();
window.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == shuffleBut) {
arrayVisualizer.shuffle(ArrayVisualizer.array);
arrayVisualizer.repaint();
}
}
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if(event.getSource() == startSort) {
if(!timer.isRunning()) { //If timer is not running
timer.setInitialDelay(0); //Set initial delay
timer.start(); //Start the timer
}
}
}
};
ActionListener sortWithDelay = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(sorted(ArrayVisualizer.array)) { //If it is sorted
timer.stop(); //Stop the timer
return;
} else {
arrayVisualizer.sort(ArrayVisualizer.array); //If it is not sorted continue the sort
arrayVisualizer.repaint(); //Called after each swap
}
}
};
private int delay = 10; //Milliseconds
private Timer timer = new Timer(delay, sortWithDelay);
private boolean sorted(int[] array) {
for(int i = 0; i < array.length - 1; i++) {
if(array[i] > array[i+1]) {
return false;
}
}
return true;
}
}
ArrayVisualizer.java:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Array;
import javax.swing.*;
import java.util.*;
public class ArrayVisualizer extends JPanel {
private static final long serialVersionUID = 1L;
private InsertionSort insertionSort = new InsertionSort();
private SelectionSort selectionSort = new SelectionSort();
protected static int[] array;
private final int REC_WIDTH = 1; //1980 rectangles
private final int NUMBER_OF_RECS = Window.WINDOW_WIDTH / REC_WIDTH;
private final int[] barColors;
public ArrayVisualizer() {
setBackground(Color.black);
array = new int[NUMBER_OF_RECS];
barColors = new int[NUMBER_OF_RECS];
generateRandom(array);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g.create();
graphics.setColor(Color.white);
for(int i = 0; i < NUMBER_OF_RECS; i++) {
int height = array[i] * 4; //Done for scaling
int recX = i + (REC_WIDTH - 1) * i; //Read fillRect documentation
int recY = Window.WINDOW_HEIGHT - height; //Read fillRect documentation
graphics.fillRect(recX, recY, REC_WIDTH, height);
}
}
//This will return the Dimension of the actual rectangles. i.e the rectangles will only exist when this exists, almost like a canvas in javascript
#Override
public Dimension getPreferredSize() {
return new Dimension(Window.WINDOW_WIDTH, Window.WINDOW_HEIGHT);
}
//Creates a random unsorted array with numbers 1-200
protected void generateRandom(int[] array) {
Random number = new Random();
for(int i = 0; i < NUMBER_OF_RECS; i++) {
array[i] = number.nextInt(200);
}
}
protected void shuffle(int[] array) {
generateRandom(array);
}
protected void sort(int[] array) {
selectionSort.sortWithDelay(array);
}
}
InsertionSort.java:
public class InsertionSort {
private int i = 1;
private int j = 0;
public void sortWithDelay(int arr[])
{
int n = arr.length;
if(i < n) {
int key = arr[i];
j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while(j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
++i;
}
}
}
SelectionSort.java:
public class SelectionSort {
private int i = 1;
private int j = 0;
public void sortWithDelay(int arr[])
{
int n = arr.length - 1;
if(i < n) {
int min_index = i;
for(int j = i + 1; j < n; j++) {
if(arr[j] < arr[min_index]) {
min_index = j;
}
}
int temp = arr[min_index];
arr[min_index] = arr[i];
arr[i] = temp;
++i;
}
}
}
Call an action with a swing timer every second that will return an intermediate array. Then paint this intermediate array. Repeat until the array is sorted.
To obtain an intermediate array, modify the InsertionSort from a static method to a class method that will store the variable i so that we can resume sorting when called again.
public class Window implements ActionListener {
//Window width
protected static int WINDOW_WIDTH = 1980;
//Window height
protected static int WINDOW_HEIGHT = 1080;
//This will draw all our rectangles
protected static ArrayVisualizer arrayVisualizer;
//Make a new JFrame
JFrame window = new JFrame();
JButton shuffleBut = new JButton("Shuffle");
JButton startSort = new JButton("Start Sorting");
public Window() {
initWindow();
}
private void addButtons() {
//Shuffle Button
shuffleBut.setBounds(100, 50, 100, 100);
shuffleBut.setBackground(Color.white);
shuffleBut.addActionListener(this);
startSort.setBounds(500, 50, 100, 100);;
startSort.setBackground(Color.white);
startSort.addActionListener(taskPerformer);
window.add(shuffleBut);
window.add(startSort);
}
private void initWindow() {
ImageIcon logo = new ImageIcon();
window = new JFrame();
window.setTitle("JAlgorithms");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
window.setLocationRelativeTo(null);
window.setResizable(false);
addButtons();
arrayVisualizer = new ArrayVisualizer();
window.add(arrayVisualizer);
arrayVisualizer.repaint(); //Will call paint component method
window.pack();
window.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == shuffleBut) {
arrayVisualizer.shuffle(ArrayVisualizer.array);
arrayVisualizer.repaint();
}
}
private int delay = 1000; // delay is 1s
private Timer timer = new Timer(delay, sortWithDelay);
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if(event.getSource() == startSort) {
// Start the timer that shows a swap every second
if(!timer.isRunning()) {
timer.setInitialDelay(0);
timer.start();
}
}
}
};
ActionListener sortWithDelay = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if(isSorted(ArrayVisualizer.array)) {
timer.stop();
return;
}
arrayVisualizer.sort(ArrayVisualizer.array);
arrayVisualizer.repaint();
}
};
private boolean isSorted(int[] arr) {
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) {
return false;
}
}
return true;
}
}
public class ArrayVisualizer extends JPanel {
private InsertionSort insertionSort = new InsertionSort();
protected static int[] array;
private final int REC_WIDTH = 1; //1980 rectangles
private final int NUMBER_OF_RECS = Window.WINDOW_WIDTH / REC_WIDTH;
public ArrayVisualizer() {
array = new int[NUMBER_OF_RECS];
generateRandom(array);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g.create();
graphics.setColor(Color.orange);
for(int i = 0; i < NUMBER_OF_RECS; i++) {
int height = array[i] * 4; //Done for scaling
int recX = i + (REC_WIDTH - 1) * i; //Read fillRect documentation
int recY = Window.WINDOW_HEIGHT - height; //Read fillRect documentation
graphics.fillRect(recX, recY, REC_WIDTH, height);
}
}
//This will return the Dimension of the actual rectangles. i.e the rectangles will only exist when this exists, almost like a canvas in javascript
#Override
public Dimension getPreferredSize() {
return new Dimension(Window.WINDOW_WIDTH, Window.WINDOW_HEIGHT);
}
//Creates a random unsorted array with numbers 1-200
protected void generateRandom(int[] array) {
Random number = new Random();
for(int i = 0; i < NUMBER_OF_RECS; i++) {
array[i] = number.nextInt(200);
}
}
protected void shuffle(int[] array) {
generateRandom(array);
}
protected void sort(int[] array) {
insertionSort.sortWithDelay(array);
}
}
public class InsertionSort {
private int i = 1;
public void sortWithDelay(int arr[])
{
int n = arr.length;
if(i < n) {
int key = arr[i];
int j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while(j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
++i;
}
}
}
I am making Conway's Game of Life using Java Swing. I am using a 2D arrays of buttons to paint the cells. The problem I have right now is that I implemented a button which will clear the pattern or patterns drew manually o randomly and also while the timer is running. I want to clear or restart the 2D array of buttons but when I try to draw it doesn't work.
Here I have the Action Listeners for each button
//Starts the timer
Starter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
cells = new JButton[size][size];
}
});
//Stops the timer
Stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
//Clears de buttons which are painted
clear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
if(Univers[i][j]){
cells[i][j].setBackground(Color.BLACK);
}
}
}
Arrays.fill(cells, null);
}
});
All the code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class GameOfLife extends JFrame{
int size=15;
int time=0;
boolean Univers[][];
JButton cells[][];
//int countentry=0;
//List<boolean[][]> Record;
JComboBox combobox;
public GameOfLife() {
//Record = new ArrayList<>();
setPreferredSize(new Dimension(600, 600));
pack();
setLayout(null);
/*combobox= new JComboBox();
combobox.addItem("Records");
combobox.addItem(time+"s");
*/
Random rnd=new Random();
Univers=new boolean[size][size];
cells=new JButton[size][size];
JPanel UniversPanel=new JPanel();
UniversPanel.setBounds(0,0,500,500);
UniversPanel.setLayout(new GridLayout(size,size));
////////////////////////////////////////////////////////////
//manual cell adding
MouseListener mouseListener = new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) { }
#Override
public void mouseReleased(MouseEvent e) { }
#Override
public void mousePressed(MouseEvent e) { }
#Override
public void mouseExited(MouseEvent e) { }
#Override
public void mouseEntered(MouseEvent e) {
JButton ch = (JButton) e.getSource();
//System.out.println(ch.getLocation(getLocation()));
int sizegrid = UniversPanel.getSize(getSize()).width / size;
int i = (ch.getLocation(getLocation()).x) / sizegrid;
int z = (ch.getLocation(getLocation()).y) / sizegrid;
//System.out.println("x= "+i);
//System.out.println("y= "+z);
if (!Univers[z][i] && SwingUtilities.isLeftMouseButton(e)) {
Univers[z][i] = true;
cells[z][i].setBackground(Color.GREEN);
}
if(Univers[z][i] && SwingUtilities.isRightMouseButton(e)) {
Univers[z][i]=false;
cells[z][i].setBackground(Color.BLACK);
}
}
};
///////////////////////////////////////////////////////////////////
for(int x=0;x<size;x++) {
for(int y=0;y<size;y++) {
/*if((x==0 && y==1 )|| (x==1 && y==1) || (x==2 && y==1)) {
Univers[x][y]=true;
}else {
Univers[x][y]=false;
}*/
Univers[x][y]=false;
//Univers[x][y]=rnd.nextInt(100)<20;
JButton btn=new JButton();
if(Univers[x][y]) {
btn.setBackground(Color.GREEN);
}else {
btn.setBackground(Color.BLACK);
}
UniversPanel.add(btn);
cells[x][y]=btn;
}
}
//Record.add(Univers);
//countentry+=1;
//System.out.print(Record.size());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int delay=100;//milliseconds
//int Timeup=5000/delay;
Timer timer=new Timer(delay,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
boolean[][] tempUnivers=new boolean[size][size];
//countentry+=1;
for(int x=0;x<size;x++) {
for(int y=0;y<size;y++) {
int count=Neigbours(x,y);
if(Univers[x][y]) {
if(count<2) {
tempUnivers[x][y]=false;
}
if(count==3 ||count==2) {
tempUnivers[x][y]=true;
}
if(count>3) {
tempUnivers[x][y]=false;
}
}else{
if(count==3)
tempUnivers[x][y]=true;
}
}
}
Univers=tempUnivers;
//Record.add(Univers);
//System.out.print(Record.size());
for(int x=0;x<size;x++) {
for(int y=0;y<size;y++) {
if(Univers[x][y]) {
cells[x][y].setBackground(Color.GREEN);
}else {
cells[x][y].setBackground(Color.BLACK);
}
}
}
/* if(countentry==Timeup) {
time+=5;
combobox.addItem(time+"s");
countentry=0;
}
*/
}
});
for(int x=0;x<size;x++) {
for(int y=0;y<size;y++) {
cells[x][y].addMouseListener(mouseListener);
}
}
//Slider
/*JPanel PanelSlider =new JPanel();
PanelSlider.setLayout(new GridLayout(0,2));
PanelSlider.setBounds(0,510,300,50);
JSlider slider = new JSlider(0,5,0);
slider.setPaintTrack(true);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMajorTickSpacing(1);
slider.setMinorTickSpacing(1/10);
slider.setBounds(51, 88, 277, 52);
PanelSlider.add(combobox);
PanelSlider.add(slider);
*/
//Buttons
JPanel PanelButton =new JPanel();
PanelButton.setLayout(new GridLayout(0,3));
PanelButton.setBounds(0,510,200,50);
JButton Starter=new JButton("Start");
PanelButton.add(Starter);
JButton Stop=new JButton("Stop");
PanelButton.add(Stop);
JButton clear = new JButton("Clear");
PanelButton.add(clear);
//Starts the timer
Starter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
cells = new JButton[size][size];
}
});
//Stops the timer
Stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
//Clears de buttons which are painted
clear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
if(Univers[i][j]){
cells[i][j].setBackground(Color.BLACK);
}
}
}
Arrays.fill(cells, null);
}
});
//add(PanelSlider);
add(UniversPanel);
add(PanelButton);
setLocationRelativeTo(null);
setVisible(true);
}
int Neigbours(int i, int z) {
int count=0;
for(int x=i-1;x<=i+1;x++) {
for(int y=z-1;y<=z+1;y++) {
try {
if(Univers[x][y]) {
count++;
}
}catch(Exception e){
//System.out.println(e);
}
}
}
if(Univers[i][z])
count--;
return count;
}
public static void main(String[] args) {
new GameOfLife();
}
//Slider info https://docs.oracle.com/javase/tutorial/uiswing/components/slider.html
//Manual insert void ActionPerformed(ActionEvent ae){add jbutton ch = (Jbutton) ae.getSource();}
}
Please read the comment within the code to follow the changes made in the code and the recommendations:
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
public class GameOfLife extends JFrame{
//declare constants
private final int BOARD_SIZE=15,
ANIMATION_DELAY=100;//milliseconds;
private final Cell cells[][];
public GameOfLife() {
//setPreferredSize(new Dimension(600, 600)); let layout manager work out the size derived from children
//setLayout(null); avoid using null layouts and seting bounds manually
cells=new Cell[BOARD_SIZE][BOARD_SIZE];
JPanel universPanel=new JPanel();
//universPanel.setBounds(0,0,500,500); let the layout manager set bounds
universPanel.setLayout(new GridLayout(BOARD_SIZE,BOARD_SIZE));
//initialize all cells
for(int x=0;x<BOARD_SIZE;x++) {
for(int y=0;y<BOARD_SIZE;y++) {
Cell cell=new Cell();
universPanel.add(cell);
cells[x][y]=cell;
}
}
//move the animation code to a method for better readability
Timer timer=new Timer(ANIMATION_DELAY,e -> animate());
//Buttons
JPanel panelButton =new JPanel();
panelButton.setLayout(new GridLayout(0,3));
//panelButton.setBounds(0,510,200,50); let the layout manager set bounds
JButton starter=new JButton("Start");
panelButton.add(starter);
JButton stop=new JButton("Stop");
panelButton.add(stop);
JButton clear = new JButton("Clear");
panelButton.add(clear);
//Starts the timer
starter.addActionListener(e -> timer.start());
//Stops the timer
stop.addActionListener(e -> timer.stop());
//Resets all cells
clear.addActionListener(e -> {
for(int i = 0; i < BOARD_SIZE; i++){
for(int j = 0; j < BOARD_SIZE; j++){
cells[i][j].setUniverse(false);
}
}
//Arrays.fill(cells, null); no need to set to null.
});
//add(PanelSlider);
//add to appropriate BorderLayout positions
add(universPanel, BorderLayout.CENTER);
add(panelButton, BorderLayout.SOUTH);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack(); //pack after you added all components
setVisible(true);
}
private void animate(){
for(int x1=0;x1<BOARD_SIZE;x1++) {
for(int y1=0;y1<BOARD_SIZE;y1++) {
int count=numberOfNeigboursAround(x1,y1);
if(cells[x1][y1].isUniverse()) {
if(count<2) {
cells[x1][y1].setUniverse(false);
}else if//process next if only if previous one was false
(count==3 ||count==2) {
cells[x1][y1].setUniverse(true);
}else if(count>3) {
cells[x1][y1].setUniverse(false);
}
}else if(count==3) {
cells[x1][y1].setUniverse(true);
}
}
}
}
private int numberOfNeigboursAround(int x, int y) {
int count=0;
for(int xIndex=x-1;xIndex<=x+1;xIndex++) {
for(int yIndex=y-1;yIndex<=y+1;yIndex++) {
//make sure index is valid
if(xIndex >= BOARD_SIZE || xIndex < 0 || yIndex >= BOARD_SIZE || yIndex < 0) {
continue;
}
//don't process center cell
if(xIndex == x&&yIndex ==y) {
continue;
}
if(cells[xIndex][yIndex].isUniverse()) {
count++;
}
}
}
return count;
}
public static void main(String[] args) {
new GameOfLife();
}
}
//Introduce a Cell class with the needed properties. Since button functionality i snot
//use a JLabel can be used to represent a cell
class Cell extends JLabel{
private static Color BOARD = Color.BLACK, UNIVERSE = Color.GREEN, BORDER = Color.GRAY;
private static Dimension CELL_SIZE = new Dimension(30,30);
private boolean universe;
public Cell() {
super();
universe = false;
setOpaque(true);
setBorder(BorderFactory.createLineBorder(BORDER, 2));
setBackground(BOARD);
//add mouse listener. use MouseInputAdapter to implement only needed methods
addMouseListener( new MouseInputAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
mouseClicksHandler(e);
}
});
}
public boolean isUniverse() {
return universe;
}
public void setUniverse(boolean isUniverse) {
if (universe == isUniverse) return; //no change
universe = isUniverse;
setBackground(isUniverse ? UNIVERSE : BOARD);
repaint();
}
private void mouseClicksHandler(MouseEvent e){
if (SwingUtilities.isLeftMouseButton(e)) {
setUniverse(true);
}else //if first if is true no need to evaluate the second if
if( SwingUtilities.isRightMouseButton(e)) {
setUniverse(false);
}
}
//preferred size used by layout managers
#Override
public Dimension getPreferredSize() {
return CELL_SIZE;
}
}
I am trying to make a basic tetris game, first I am looking to draw a grid to make sure that I am creating blocks as I want to, however I can't get my program to access my paintComponent method.
package tetris;
import javax.swing.*;
import java.awt.*;
public class TetrisMain extends JFrame {
final int BoardWidth = 10;
final int BoardHeight = 20;
public static int HEIGHT = 400;
public static int WIDTH = 200;
Timer timer;
boolean isFallingFinished = false;
boolean isStarted = false;
boolean isPaused = false;
int score = 0;
int curX = 0;
int curY = 0;
int[][] grid = new int[BoardWidth][BoardHeight];
public static void main(String[] args) {
JFrame frame = new JFrame("Charles Walker - 1504185");
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
frame.repaint();
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
g.setColor(Color.BLACK);
for (int i = 0; i < BoardWidth; i++) {
for (int j = 0; j < BoardHeight; j++) {
curX = grid[i][curY];
curY = grid[curX][j];
g.fillRect(WIDTH / BoardWidth, HEIGHT / BoardHeight, curX, curY);
}
}
}
}
Here is a basic code to do what you want :
import javax.swing.JFrame;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.*;
public class Name extends JFrame {
public Name() {
super("Name");
setTitle("Application");
setContentPane(new Pane());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setResizable(true);
setVisible(true);
while (true){
try { //Update screen every 33 miliseconds = 25 FPS
Thread.sleep(33);
} catch(InterruptedException bug) {
Thread.currentThread().interrupt();
System.out.println(bug);
}
repaint();
}
}
class Pane extends JPanel {
public void paintComponent(Graphics g) { //Here is were you can draw your stuff
g.drawString("Hello World",0,20); //Display text
}
}
public static void main(String[] args){
new Name();
}
}
I think you forgot that line to set the content pane :
setContentPane(new Pane());
and, important, you need a while loop to redraw :
while (true){
try { //Update screen every 33 miliseconds = 25 FPS
Thread.sleep(33);
} catch(InterruptedException bug) {
Thread.currentThread().interrupt();
System.out.println(bug);
}
repaint();
}
I need help with drawing the grids to the GUI as well as the program later letting me change the colour of the boxes drawn. I know i will have to use paintComponent(Graphics g), but i have no idea how or where.
So here is a copy of the code i have got so far ( even though i have been told it can be quite daunting just being given code i think it is the best way for people to help and not just do it for me). From the top it sets values, creates the GUI, calls the GUI, fills a 2d array with boxes( i think). Then in the Boxes class setting values the boxes class will need, then the start of how to draw them (didn't know how to work it out), then some seta methods for the x and y coordinates.
what i would like you to do is show how to have the boxes be drawn to the Jpanel, to make a grid and then to show me how to change the colour to different shades of blue, depending on a external value.
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import javax.swing.*;
public class NewGrid {
Boxes[][] Boxs;
int BoxesX;
int BoxesY;
NewGrid() {
buildtheGUI();
}
JFrame frame = new JFrame();
JPanel panel = new JPanel();
public void buildtheGUI() {
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
new NewGrid();
}
public void addboxes() {
Boxs = new Boxes[panel.getWidth() / 10][panel.getHeight() / 10];
for (int i = 0; i < panel.getWidth() / 10; i++) {
for (int j = 0; j < panel.getHeight() / 10; j++) {
Boxs[i][j] = new Boxes();
Boxs[i][j].setx(i * (panel.getWidth() / 10));
Boxs[i][j].sety(j * (panel.getHeight() / 10));
Boxs[i][j].draw(null);
}
}
}
}
public class Boxes extends JPanel {
int x;
int y;
int width = 10;
int hieight = 10;
Color colour = Color.BLACK;
public void draw(Graphics g) {
g.setColor(colour);
g.fillRect(x, y, width, hieight);
}
public void setx(int i ){
x = i;
}
public void sety(int i ){
y = i;
}
}
I can't comment something, to try to make things easier,
I code there box.putClientProperty(unique_identifier, value_for_identifier), you can to multiple this method as you want
from every Swing Listener you can to get this and proper coordinated defined in putClientProperty
.
JComponent comp = event.getComponent();
String strRow = (String) comp.getClientProperty("row");
String strColumn = (String) comp.getClientProperty("column");
simple code
import java.awt.*;
import java.awt.Graphics;
import java.util.*;
import javax.swing.*;
public class NewGrid {
private int row = 10;
private int column = 10;
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
private NewGrid() {
addboxes();
panel.setLayout(new GridLayout(row, column));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private void addboxes() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
Boxes box = new Boxes();
box.putClientProperty("row", row);
box.putClientProperty("column", column);
panel.add(box);
}
}
}
public static void main(String[] args) {
Runnable doRun = new Runnable() {
#Override
public void run() {
new NewGrid();
}
};
SwingUtilities.invokeLater(doRun);
}
}
class Boxes extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(20, 20);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(20, 20);
}
#Override
public void paintComponent(Graphics g) {
int margin = 2;
Dimension dim = getSize();
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(margin, margin, dim.width - margin * 2,
dim.height - margin * 2);
}
}