java swing setlocation doesn't work for second time - java

Frame has mainContentPane with layout manager = null
mainContentPane gamePanel, which holds jLabel Background at z-order 1 and a bunch of backgammon stones at z- order 0, if i set their positions before adding them to game panel, they end up in places i need them to be, but if im trying to set their places in game they all end ap at point 0,0 and calling get location says that its at a different location. Plese help me out on what im doing wrong with swing layout etc. setStones is the void that suppose to do it and getLocation after it ran gives locations I need, but everything is still at 0,0 on the screen
public class MainWindow extends JFrame implements ActionListener, ItemListener,
MouseListener, MouseMotionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private final int NUMBER_OF_STONES = 30;
private JPanel mainContentPane;
private JLayeredPane gamePanel;
private JLabel background;
private JMenuBar menuBar;
private JMenu menuGameTitle, aboutGameTitle;
private JMenuItem newGame, exit, help;
private JLabel[] stones;
private Dimension preferredSize;
private int stoneDragged = NUMBER_OF_STONES;
private int clickX = 0;
private int clickY = 0;
private HashMap<game.Color, String> stoneImage;
private HashMap<Integer, int[]> locations;
private int currStone;
public MainWindow() {
createGUI();
stoneImage = new HashMap<game.Color, String>();
stoneImage.put(game.Color.BLACK, "SilverNSH.jpg");
stoneImage.put(game.Color.WHITE, "GoldNSH.jpg");
locations = new HashMap<Integer, int[]>();
locations.put(0, new int[] {355,509});
locations.put(1, new int[] {655, 509});
.....
currStone = 0;
play();
}
private void createGUI() {
preferredSize = new Dimension(800, 600);
mainContentPane = new JPanel();
mainContentPane.setLayout(null);
mainContentPane.setPreferredSize(preferredSize);
gamePanel = new JLayeredPane();
gamePanel.setBounds(0, 0, 800, 600);
setSize(preferredSize);
background = new JLabel(new ImageIcon("BackGammon.jpg"));
// adding stones;
initStones();
for (int i = 0; i < stones.length; i++) {
gamePanel.add(stones[i], 0);
}
// setting background to 1 Z order
gamePanel.add(background, 1);
// set Z level to 0
for (int i = 0; i < stones.length; i++) {
gamePanel.setComponentZOrder(stones[i], 0);
}
mainContentPane.add(gamePanel);
setContentPane(mainContentPane);
pack();
}
private void initStones() {
stones = new JLabel[NUMBER_OF_STONES];
for (int i = 0; i < stones.length; i++) {
if (i < NUMBER_OF_STONES / 2) {
stones[i] = new JLabel(new ImageIcon("SilverNSH.gif"));
} else {
stones[i] = new JLabel(new ImageIcon("GoldNSH.gif"));
}
stones[i].setName(i + "");
stones[i].setSize(40,40);
stones[i].addMouseListener(this);
stones[i].addMouseMotionListener(this);
}
}
#Override
public void mousePressed(MouseEvent e) {
stoneDragged = Integer.parseInt(e.getComponent().getName());
clickX = e.getX();
clickY = e.getY();
}
#Override
public void mouseReleased(MouseEvent e) {
// no stone is dragged
stoneDragged = NUMBER_OF_STONES;
}
#Override
public void mouseDragged(MouseEvent e) {
// off screen check
int yLoc;
int xLoc;
if (stoneDragged >= 0 && stoneDragged < NUMBER_OF_STONES) {
xLoc = e.getComponent().getX() + e.getX() - clickX;
yLoc = e.getComponent().getY() + e.getY() - clickY;
stones[stoneDragged].setLocation(xLoc, yLoc);
if (stones[stoneDragged].getX() <= 50)
stones[stoneDragged].setLocation(51, 51);
if (stones[stoneDragged].getY() <= 50)
stones[stoneDragged].setLocation(51, 51);
if (stones[stoneDragged].getX() >= 660)
stones[stoneDragged].setLocation(659, 509);
if (stones[stoneDragged].getY() >= 510)
stones[stoneDragged].setLocation(659, 509);
}
}
private void play() {
setStones(board.getAmountArray(), board.getColorArray());
}
private void setStones(int[] amountArray, game.Color[] colorArray) {
currStone = 0;
for (int i = 0; i < Board.NO_OF_PLAYABLE_FIELDS;i++){
if (amountArray[i] != 0) {
placeStones(i, amountArray[i], stoneImage.get(colorArray[i]));
}
}
}
private void placeStones(int startPos, int amount, String picture) {
for (int i = 0; i < amount;i++){
stones[currStone].setIcon(new ImageIcon(picture));;
if (startPos < 13) {
stones[currStone].setLocation(locations.get(startPos)[0], locations.get(startPos)[1] - i*40);
} else {
stones[currStone].setLocation(locations.get(startPos)[0], locations.get(startPos)[1] + i*40);
}
stones[currStone].setSize(40, 40);
currStone++;
}
}
}

Related

Java Swing actionPerformed() skips visualization

I am working on my first sorting visualizer using java and swing. If i hard code selection sort, the visualizer works properly. Its when i add the actionPerformed() method to the "sort" JButton things start going wrong. The program now waits until the sort is done before it repaints. Is there a way around this?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SortingAlgorithmVisualizer implements ActionListener {
private static final int WINDOW_WIDTH = 1200;
private static final int WINDOW_HEIGHT = 600;
private static final String[] ALGORITHM_NAMES = { "Selection Sort", "Insertion Sort", "Quick Sort", "Merge Sort" };
// JFrame to create GUI window
private JFrame window;
private Sort array;
private JButton sortButton;
private JComboBox<String> algorithmMenu;
// Constructor
public SortingAlgorithmVisualizer() {
// Construct the JFrame and add components
addComponents();
// Set Basic JFrame Settings
frameSetup();
// Unsort the array
array.unsort();
}
// Construct the JFrame and add components
public void addComponents() {
window = new JFrame("Sorting Algorith Visualiser");
array = new Sort();
sortButton = new JButton("Sort");
sortButton.addActionListener(this);
algorithmMenu = new JComboBox<>(ALGORITHM_NAMES);
// algorithmMenu.addActionListener(this);
window.add(algorithmMenu, BorderLayout.PAGE_START);
window.add(array, BorderLayout.CENTER);
window.add(sortButton, BorderLayout.SOUTH);
}
// Set Basic JFrame Settings
public void frameSetup() {
window.setLocationRelativeTo(null);
window.setResizable(false);
window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == sortButton) {
array.selectionSort();
}
}
public static void main(String[] args) {
SortingAlgorithmVisualizer vis = new SortingAlgorithmVisualizer();
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Sort extends JPanel {
private static final long serialVersionUID = 1L;
private static final int ARRAY_SIZE = 25;
private static final int WINDOW_WIDTH = 1200;
private static final int WINDOW_HEIGHT = 600;
private static int barWidth = WINDOW_WIDTH / ARRAY_SIZE;
private int[] elementColor;
// Array to sort
private int[] array;
// Contructor
public Sort() {
// DO SOMETHING WITH THIS!!!!
array = new int[ARRAY_SIZE];
elementColor = new int[ARRAY_SIZE];
// Fill Array
for (int i = 0; i < ARRAY_SIZE; i++) {
array[i] = i + 1;
elementColor[i] = 0;
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
for (int i = 0; i < ARRAY_SIZE; i++) {
int height = (array[i] * 20 + 100);
int x = i + (barWidth - 1) * i;
int y = WINDOW_HEIGHT - height;
g.fillRect(x, y, barWidth, height);
}
}
public void unsort() {
int shuffles = 100;
for (int i = 0; i < shuffles; i++) {
int rand1 = (int) (Math.random() * ARRAY_SIZE);
int rand2 = (int) (Math.random() * ARRAY_SIZE);
int temp = array[rand1];
array[rand1] = array[rand2];
array[rand2] = temp;
}
}
public void selectionSort() {
int n = ARRAY_SIZE;
// Loop thought unsorted array
for (int i = 0; i < n - 1; i++) {
// Set Current Min
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (array[j] < array[minIndex])
minIndex = j;
}
// Swap the min element with the first element
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
// Repaints the Array after every swap
repaint();
wait(1000);
}
}
public void insertionSort() {
}
public void quickSort() {
}
public void mergeSort() {
}
// Wait fuction for visualisation delay
public static void wait(int ms) {
try {
Thread.sleep(ms);
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}

JavaFX memory game (trouble hiding the values of the tiles)

I'm making a memory game for school and I'm having a bit of trouble hiding the tiles in my gridpane.
I've got a seperate class where I use my eventhandlers.
I used an ObservableList to fill in my gridpane with tiles but I got no idea how to make them disappear. Thanks for taking a look , I tried to use a FadeTransition in the view class.
View
public class GameView extends GridPane {
private static final int PAREN = 10;
private Label scoreSpeler1;
private Label countDown;
private Label title;
private final static Color backgroundColor = Color.rgb(225, 93, 68);
int waarde = 0;
ObservableList<Button> vakken;
public GameView() {
this.initialiseNodes();
this.layoutNodes();
this.verdwijnWaarde();
this.toonWaarde();
}
private void initialiseNodes() {
scoreSpeler1 = new Label("Score: 0");
countDown = new Label("Tijd: 60");
title = new Label("Memory");
/*knoppen met cijfers*/
vakken = FXCollections.observableArrayList(new ArrayList<>());
for (int i = 0; i < PAREN; i++) {
vakken.add(new Button(String.valueOf(waarde)));
vakken.add(new Button(String.valueOf(waarde)));
waarde++;
}
FXCollections.shuffle(vakken);
}
private void layoutNodes() {
//score en tijd plaatsen
this.add(scoreSpeler1, 0, 0);
this.add(title, 2, 0);
this.add(countDown, 4, 0);
//memory knoppen plaatsen
int k = 0;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 4; j++) {
this.add(vakken.get(k), i, j + 2);
k++;
}
}
//label uiterlijk
GridPane.setHalignment(countDown, HPos.RIGHT);
GridPane.setHalignment(title, HPos.CENTER);
title.setId("titelGame");
scoreSpeler1.setId("scoreSpeler1");
countDown.setId("countDown");
//button/memory uiterlijk
for (Button button : vakken) {
button.setPrefHeight(120);
button.setPrefWidth(90);
}
//gridpane uiterlijk
this.setGridLinesVisible(false);
this.setBackground(new Background(new BackgroundFill(backgroundColor, null, null)));
this.setHgap(15);
this.setVgap(15);
this.setPadding(new Insets(10, 10, 10, 10));
this.autosize();
this.setAlignment(Pos.CENTER);
}
public void verdwijnWaarde() {
FadeTransition verstopWaardes = new FadeTransition();
verstopWaardes.durationProperty(Duration.seconds(2), this.vakken.get(1));
verstopWaardes.setToValue(0);
verstopWaardes.play();
}
public void toonWaarde() {
FadeTransition toonWaardes = new FadeTransition();
toonWaardes.durationProperty(Duration.seconds(0.5), vakken);
toonWaardes.setToValue(1);
toonWaardes.play();
}
}
presenter
public class GamePresenter {
private MemoryModel model;
private GameView gameView;
public GamePresenter(MemoryModel model, GameView gameView){
this.model = model;
this.gameView = gameView;
addEventHandlers();
}
private void addEventHandlers(){
gameView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
gameView.toonWaarde();
}
});
}
private void updateView(){
}
public void addWindowEventHandlers(){
}
}

How to have a MotionListener called on a JPanel that is covered

This question is to help me solve my other question. I have a JPanel that is completely covered by JLabels. I have added a MotionListener to the panel but it is never called since the labels are in the way. If I remove the labels my MotionnListener is called properly.
Is there a way I can have the covered panel see the motion events?
public class ChangesAttempt extends JPanel {
private static final long serialVersionUID = -8031881678612431401L;
static JFrame frame;
static JPanel grid;
static JLabel[][] squares;
static boolean[][] litSquares;
static int size, boardSize;
MouseEvent listener = new MouseEvent();
MotionListener mListerner = new MotionListener();
Color backGround = Color.BLUE;
Color selected = Color.PINK;
public ChangesAttempt(int size) {
ChangesAttempt.size = size;
squares = new JLabel[size][size];
litSquares = new boolean[size][size];
grid = new JPanel(new GridLayout(size, size));
grid.addMouseMotionListener(mListerner);
/*Coment out setBoard(); below to see the mousedDragged method actually being called
since the JLabels will not be in the way.*/
setBoard();
frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(grid, BorderLayout.CENTER);
frame.setTitle("ChangedLife");
if (25 * size < 525)
boardSize = 525;
else
boardSize = 25 * size;
frame.setSize(boardSize, boardSize);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class MouseEvent implements MouseListener {
#Override
public void mousePressed(java.awt.event.MouseEvent e) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (e.getSource() == squares[i][j]) {
if (litSquares[i][j] == false) {
squares[i][j].setBackground(selected);
litSquares[i][j] = true;
} else {
squares[i][j].setBackground(backGround);
litSquares[i][j] = false;
}
}
}
}
}
#Override
public void mouseClicked(java.awt.event.MouseEvent e) {
}
#Override
public void mouseEntered(java.awt.event.MouseEvent e) {
}
#Override
public void mouseExited(java.awt.event.MouseEvent e) {
}
#Override
public void mouseReleased(java.awt.event.MouseEvent e) {
}
}
class MotionListener implements MouseMotionListener {
#Override
public void mouseDragged(java.awt.event.MouseEvent e) {
Point p = e.getPoint();
System.out.println("mouse Dragged to " + p);
}
#Override
public void mouseMoved(java.awt.event.MouseEvent e) {
// TODO Auto-generated method stub
}
}
public void setBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
squares[i][j] = new JLabel();
squares[i][j].addMouseListener(listener);
squares[i][j].setOpaque(true);
squares[i][j].setBackground(backGround);
grid.add(squares[i][j]);
}
}
}
class MyLabel extends JLabel {
private static final long serialVersionUID = -1414933339546989142L;
}
public static void main(String args[]) {
new ChangesAttempt(20);
}
}
There's no "easy" way to achieve this, it might be better to move all you mouse listeners to the panel instead.
This would require you to look up the component (that's within the parent component) at the specified click point, for example...
#Override
public void mousePressed(java.awt.event.MouseEvent e) {
Component component = e.getComponent();
Component source = component.getComponentAt(e.getPoint());
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (source == squares[i][j]) {
if (litSquares[i][j] == false) {
squares[i][j].setBackground(selected);
litSquares[i][j] = true;
} else {
squares[i][j].setBackground(backGround);
litSquares[i][j] = false;
}
}
}
}
}
This will work, if you remove the MouseListener from the labels and instead, add it to the grid, allowing with your MouseMotionListener

Fixing method latency in Java

Another problem, same program:
The following is MainGUI.java
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class MainGUI extends JFrame implements ActionListener
{
private static final long serialVersionUID = 4149825008429377286L;
private final double version = 8;
public static int rows;
public static int columns;
private int totalCells;
private MainCell[] cell;
public static Color userColor;
JTextField speed = new JTextField("250");
Timer timer = new Timer(250,this);
String generationText = "Generation: 0";
JLabel generationLabel = new JLabel(generationText);
int generation = 0;
public MainGUI(String title, int r, int c)
{
rows = r;
columns = c;
totalCells = r*c;
System.out.println(totalCells);
cell = new MainCell[totalCells];
setTitle(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Timer set up
timer.setInitialDelay(Integer.parseInt(speed.getText()));
timer.setActionCommand("timer");
//set up menu bar
JMenuBar menuBar = new JMenuBar();
JMenu optionsMenu = new JMenu("Options");
JMenu aboutMenu = new JMenu("About");
menuBar.add(optionsMenu);
menuBar.add(aboutMenu);
JMenuItem helpButton = new JMenuItem("Help!");
helpButton.addActionListener(this);
helpButton.setActionCommand("help");
aboutMenu.add(helpButton);
JMenuItem aboutButton = new JMenuItem("About");
aboutButton.addActionListener(this);
aboutButton.setActionCommand("about");
aboutMenu.add(aboutButton);
JMenuItem colorSelect = new JMenuItem("Select a Custom Color");
colorSelect.addActionListener(this);
colorSelect.setActionCommand("colorSelect");
optionsMenu.add(colorSelect);
JMenuItem sizeChooser = new JMenuItem("Define a Custom Size");
sizeChooser.addActionListener(this);
sizeChooser.setActionCommand("sizeChooser");
optionsMenu.add(sizeChooser);
//Create text field to adjust speed and its label
JPanel speedContainer = new JPanel();
JLabel speedLabel = new JLabel("Enter the speed of a life cycle (in ms):");
speedContainer.add(speedLabel);
speedContainer.add(speed);
speedContainer.add(generationLabel);
Dimension speedDim = new Dimension(100,25);
speed.setPreferredSize(speedDim);
//Create various buttons
JPanel buttonContainer = new JPanel();
JButton randomizerButton = new JButton("Randomize");
randomizerButton.addActionListener(this);
randomizerButton.setActionCommand("randomize");
buttonContainer.add(randomizerButton);
JButton nextButton = new JButton("Next"); //forces a cycle to occur
nextButton.addActionListener(this);
nextButton.setActionCommand("check");
buttonContainer.add(nextButton);
JButton startButton = new JButton("Start");
startButton.addActionListener(this);
startButton.setActionCommand("start");
buttonContainer.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(this);
stopButton.setActionCommand("stop");
buttonContainer.add(stopButton);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(this);
clearButton.setActionCommand("clear");
buttonContainer.add(clearButton);
//holds the speed container and button container, keeps it neat
JPanel functionContainer = new JPanel();
BoxLayout functionLayout = new BoxLayout(functionContainer, BoxLayout.PAGE_AXIS);
functionContainer.setLayout(functionLayout);
functionContainer.add(speedContainer);
speedContainer.setAlignmentX(CENTER_ALIGNMENT);
functionContainer.add(buttonContainer);
buttonContainer.setAlignmentX(CENTER_ALIGNMENT);
//finish up with the cell container
GridLayout cellLayout = new GridLayout(rows,columns);
JPanel cellContainer = new JPanel(cellLayout);
cellContainer.setBackground(Color.black);
int posX = 0;
int posY = 0;
for(int i=0;i<totalCells;i++)
{
MainCell childCell = new MainCell();
cell[i] = childCell;
childCell.setName(String.valueOf(i));
childCell.setPosX(posX);
posX++;
childCell.setPosY(posY);
if(posX==columns)
{
posX = 0;
posY++;
}
cellContainer.add(childCell);
childCell.deactivate();
Graphics g = childCell.getGraphics();
childCell.paint(g);
}
//make a default color
userColor = Color.yellow;
//change icon
URL imgURL = getClass().getResource("images/gol.gif");
ImageIcon icon = new ImageIcon(imgURL);
System.out.println(icon);
setIconImage(icon.getImage());
//add it all up and pack
JPanel container = new JPanel();
BoxLayout containerLayout = new BoxLayout(container, BoxLayout.PAGE_AXIS);
container.setLayout(containerLayout);
container.add(cellContainer);
container.add(functionContainer);
add(menuBar);
setJMenuBar(menuBar);
add(container);
pack();
}
private void checkCells()
{
//perform check for every cell
for(int i=0;i<totalCells;i++)
{
cell[i].setNeighbors(checkNeighbors(i));
}
//use value from check to determine life
for(int i=0;i<totalCells;i++)
{
int neighbors = cell[i].getNeighbors();
if(cell[i].isActivated())
{
System.out.println(cell[i].getName()+" "+neighbors);
if(neighbors==0||neighbors==1||neighbors>3)
{
cell[i].deactivate();
}
}
if(cell[i].isActivated()==false)
{
if(neighbors==3)
{
cell[i].activate();
}
}
}
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("randomize"))
{
Random rn = new Random();
for(int i=0;i<totalCells;i++)
{
cell[i].deactivate();
if(rn.nextInt(6)==0)
{
cell[i].activate();
}
}
}
//help button, self-explanatory
if(e.getActionCommand().equals("help"))
{
JOptionPane.showMessageDialog(this, "The game is governed by four rules:\nFor a space that is 'populated':"
+ "\n Each cell with one or no neighbors dies, as if by loneliness."
+ "\n Each cell with four or more neighbors dies, as if by overpopulation."
+ "\n Each cell with two or three neighbors survives."
+ "\nFor a space that is 'empty' or 'unpopulated':"
+ "\n Each cell with three neighbors becomes populated."
+ "\nLeft click populates cells. Right click depopulates cells.","Rules:",JOptionPane.PLAIN_MESSAGE);
}
//shameless self promotion
if(e.getActionCommand().equals("about"))
{
JOptionPane.showMessageDialog(this, "Game made and owned by *****!"
+ "\nFree usage as see fit, but give credit where credit is due!\nVERSION: "+version,"About:",JOptionPane.PLAIN_MESSAGE);
}
//clears all the cells
if(e.getActionCommand().equals("clear"))
{
timer.stop();
generation = 0;
generationText = "Generation: "+generation;
generationLabel.setText(generationText);
for(int i=0;i<totalCells;i++)
{
cell[i].deactivate();
}
}
//starts timer
if(e.getActionCommand().equals("start"))
{
if(Integer.parseInt(speed.getText())>0)
{
timer.setDelay(Integer.parseInt(speed.getText()));
timer.restart();
}
else
{
JOptionPane.showMessageDialog(this, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
}
}
//stops timer
if(e.getActionCommand().equals("stop"))
{
timer.stop();
}
//run when timer
if(e.getActionCommand().equals("timer"))
{
generation++;
generationText = "Generation: "+generation;
generationLabel.setText(generationText);
timer.stop();
checkCells();
timer.setInitialDelay(Integer.parseInt(speed.getText()));
timer.restart();
}
//see checkCells()
if(e.getActionCommand().equals("check"))
{
generation++;
generationText = "Generation: "+generation;
generationLabel.setText(generationText);
checkCells();
}
//color select gui
if(e.getActionCommand().equals("colorSelect"))
{
userColor = JColorChooser.showDialog(this, "Choose a color:", userColor);
if(userColor==null)
{
userColor = Color.yellow;
}
}
//size chooser!
if(e.getActionCommand().equals("sizeChooser"))
{
SizeChooser size = new SizeChooser();
size.setLocationRelativeTo(null);
size.setVisible(true);
}
}
private int checkNeighbors(int c)
{
//if a LIVE neighbor is found, add one
int neighbors = 0;
if(cell[c].getPosX()!=0&&cell[c].getPosY()!=0)
{
if(c-columns-1>=0)
{
if(cell[c-columns-1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-columns-1].getName());
neighbors++;
}
}
}
if(cell[c].getPosY()!=0)
{
if(c-columns>=0)
{
if(cell[c-columns].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-columns].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=columns-1&&cell[c].getPosY()!=0)
{
if(c-columns+1>=0)
{
if(cell[c-columns+1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-columns+1].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=0)
{
if(c-1>=0)
{
if(cell[c-1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c-1].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=columns-1)
{
if(c+1<totalCells)
{
if(cell[c+1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+1].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=0&&cell[c].getPosY()!=rows-1)
{
if(c+columns-1<totalCells)
{
if(cell[c+columns-1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+columns-1].getName());
neighbors++;
}
}
}
if(cell[c].getPosY()!=rows-1&&cell[c].getPosY()!=rows-1)
{
if(c+columns<totalCells)
{
if(cell[c+columns].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+columns].getName());
neighbors++;
}
}
}
if(cell[c].getPosX()!=columns-1&&cell[c].getPosY()!=rows-1)
{
if(c+columns+1<totalCells)
{
if(cell[c+columns+1].isActivated())
{
System.out.println(cell[c].getName()+" found "+cell[c+columns+1].getName());
neighbors++;
}
}
}
return neighbors;
}
}
The following is MainCell.java:
public class MainCell extends JPanel implements MouseListener
{
//everything here should be self-explanatory
private static final long serialVersionUID = 1761933778208900172L;
private boolean activated = false;
public static boolean leftMousePressed;
public static boolean rightMousePressed;
private int posX = 0;
private int posY = 0;
private int neighbors = 0;
private URL cellImgURL_1 = getClass().getResource("images/cellImage_1.gif");
private ImageIcon cellImageIcon_1 = new ImageIcon(cellImgURL_1);
private Image cellImage_1 = cellImageIcon_1.getImage();
private URL cellImgURL_2 = getClass().getResource("images/cellImage_2.gif");
private ImageIcon cellImageIcon_2 = new ImageIcon(cellImgURL_2);
private Image cellImage_2 = cellImageIcon_2.getImage();
private URL cellImgURL_3 = getClass().getResource("images/cellImage_3.gif");
private ImageIcon cellImageIcon_3 = new ImageIcon(cellImgURL_3);
private Image cellImage_3 = cellImageIcon_3.getImage();
public MainCell()
{
Dimension dim = new Dimension(17, 17);
setPreferredSize(dim);
addMouseListener(this);
}
public void activate()
{
setBackground(MainGUI.userColor);
System.out.println(getName()+" "+posX+","+posY+" activated");
setActivated(true);
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(getPosX()==MainGUI.columns-1&&getPosY()==0)
{
//do nothing
}
else if(getPosY()!=0&&getPosX()!=MainGUI.columns-1)
{
g.drawImage(cellImage_1,0,0,null);
}
else if(getPosY()==0)
{
g.drawImage(cellImage_2,0,0,null);
}
else if(getPosX()==MainGUI.columns-1)
{
g.drawImage(cellImage_3,0,0,null);
}
}
public void setActivated(boolean b)
{
activated = b;
}
public void deactivate()
{
setBackground(Color.gray);
System.out.println(getName()+" "+posX+","+posY+" deactivated");
setActivated(false);
}
public boolean isActivated()
{
return activated;
}
public void setNeighbors(int i)
{
neighbors = i;
}
public int getNeighbors()
{
return neighbors;
}
public int getPosX()
{
return posX;
}
public void setPosX(int x)
{
posX = x;
}
public int getPosY()
{
return posY;
}
public void setPosY(int y)
{
posY = y;
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
if(leftMousePressed&&SwingUtilities.isLeftMouseButton(e))
{
activate();
}
if(rightMousePressed&&SwingUtilities.isRightMouseButton(e))
{
deactivate();
}
}
public void mouseExited(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
if(SwingUtilities.isRightMouseButton(e)&&!leftMousePressed)
{
deactivate();
rightMousePressed = true;
}
if(SwingUtilities.isLeftMouseButton(e)&&!rightMousePressed)
{
activate();
leftMousePressed = true;
}
}
public void mouseReleased(MouseEvent e)
{
if(SwingUtilities.isRightMouseButton(e))
{
rightMousePressed = false;
}
if(SwingUtilities.isLeftMouseButton(e))
{
leftMousePressed = false;
}
}
}
The following is SizeChooser.java:
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.swing.*;
public class SizeChooser extends JFrame
{
private static final long serialVersionUID = -6431709376438241788L;
public static MainGUI GUI;
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
JTextField rowsTextField = new JTextField(String.valueOf((screenSize.height/17)-15));
JTextField columnsTextField = new JTextField(String.valueOf((screenSize.width/17)-10));
private static int rows = screenSize.height/17-15;
private static int columns = screenSize.width/17-10;
public SizeChooser()
{
setResizable(false);
setTitle("Select a size!");
JPanel container = new JPanel();
BoxLayout containerLayout = new BoxLayout(container, BoxLayout.PAGE_AXIS);
container.setLayout(containerLayout);
add(container);
JLabel rowsLabel = new JLabel("Rows:");
container.add(rowsLabel);
container.add(rowsTextField);
JLabel columnsLabel = new JLabel("Columns:");
container.add(columnsLabel);
container.add(columnsTextField);
JButton confirmSize = new JButton("Confirm");
confirmSize.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
GUI.setVisible(false);
GUI = null;
if(Integer.parseInt(rowsTextField.getText())>0)
{
rows = Integer.parseInt(rowsTextField.getText());
}
else
{
JOptionPane.showMessageDialog(rootPane, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
}
if(Integer.parseInt(columnsTextField.getText())>0)
{
columns = Integer.parseInt(columnsTextField.getText());
}
else
{
JOptionPane.showMessageDialog(rootPane, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
}
GUI = new MainGUI("The Game of Life!", rows, columns);
GUI.setLocationRelativeTo(null);
GUI.setVisible(true);
setVisible(false);
}
});
container.add(confirmSize);
URL imgURL = getClass().getResource("images/gol.gif");
ImageIcon icon = new ImageIcon(imgURL);
System.out.println(icon);
setIconImage(icon.getImage());
pack();
}
public static void main(String[]args)
{
GUI = new MainGUI("The Game of Life!", rows, columns);
GUI.setLocationRelativeTo(null);
GUI.setVisible(true);
}
}
So the problem now is, when the randomize button is pressed, or a large number of cells exist and then the timer is started, the cells aren't as snappy as they would be with less active cells. For example, with 100 columns and 50 rows, when the randomize button is pressed, one cell activates, then the next, then another, and so forth. Can I have them all activate at exactly the same time? Is this just a problem with too many things calculated at once? Would concurrency help?
QUICK EDIT: Is the swing timer the best idea for this project?
I havent read through your code completely but I am guessing that your listener methods are fairly computationally intensive and hence the lag in updating the display.
This simple test reveals that your randomize operation should be fairly quick:
public static void main(String args[]) {
Random rn = new Random();
boolean b[] = new boolean[1000000];
long timer = System.nanoTime();
for (int i = 0; i < b.length; i++) {
b[i] = rn.nextInt(6) == 0;
}
timer = System.nanoTime() - timer;
System.out.println(timer + "ns / " + (timer / 1000000) + "ms");
}
The output for me is:
17580267ns / 17ms
So this leads me into thinking activate() or deactivate() is causing your UI to be redrawn.
I am unable to run this because I don't have your graphical assets, but I would try those changes to see if it works:
In MainGUI#actionPerformed, change:
if(e.getActionCommand().equals("randomize"))
{
Random rn = new Random();
for(int i=0;i<totalCells;i++)
{
cell[i].deactivate();
if(rn.nextInt(6)==0)
{
cell[i].activate();
}
}
}
to:
if(e.getActionCommand().equals("randomize"))
{
Random rn = new Random();
for(int i=0;i<totalCells;i++)
{
// This will not cause the object to be redrawn and should
// be a fairly cheap operation
cell[i].setActivated(rn.nextInt(6)==0);
}
// Cause the UI to repaint
repaint();
}
Add this to MainCell
// You can specify those colors however you like
public static final Color COLOR_ACTIVATED = Color.RED;
public static final Color COLOR_DEACTIVATED = Color.GRAY;
And change:
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(getPosX()==MainGUI.columns-1&&getPosY()==0)
{
//do nothing
}
to:
protected void paintComponent(Graphics g)
{
// We now make UI changes only when the component is painted
setBackground(activated ? COLOR_ACTIVATED : COLOR_DEACTIVATED);
super.paintComponent(g);
if(getPosX()==MainGUI.columns-1&&getPosY()==0)
{
//do nothing
}

Swing Timers and Animations in JPanel

Im trying to animate 2 boxes to go from the top right to the bottom left of a JPanel. For the animation I'm using a Swing Timer and SwingUtilities.invokeLater(). The problem is that when I click the start button. It only animates and moves the blue box, but not the red one.
Heres the code:
//import neccessary stuff
public class Example extends JFrame {
public static void main(String[] args) {
Example e = new Example();
e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
e.setSize(600, 565);
e.setVisible(true);
}</code>
private JButton startButton = new JButton("Start");
private JPanel theTable = new table();
public Example() {
add(startButton, BorderLayout.SOUTH);
add(theTable, BorderLayout.CENTER);
Handler handler = new Handler();
startButton.addActionListener(handler);
}
public ArrayList<Integer> xPos, yPos;
final int START_POSITION_X = 470;
final int START_POSITION_Y = 10;
final int[] END_POSITION_X = {70, 87};
final int END_POSITION_Y = 160;
private class table extends JPanel {
public table() {
xPos = new ArrayList<Integer>();
yPos = new ArrayList<Integer>();
xPos.add(START_POSITION_X); //default position for box1
yPos.add(START_POSITION_Y);
xPos.add(START_POSITION_X); //default position for box2
yPos.add(START_POSITION_Y);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(new Color(-16756217));
g.setColor(Color.RED);
g.fillRect(xPos.get(1), yPos.get(1), 89, 129);
g.setColor(Color.BLUE);
g.fillRect(xPos.get(0), yPos.get(0), 89, 129);
if (isAnimating) {
animator.start();
} else {
animator.stop();
isAnimating = false;
}
}
}
private class Handler implements ActionListener {
public void actionPerformed(ActionEvent e) {
Runnable r1 = new Runnable() {
#Override
public void run() {
animateCard(0, END_POSITION_X[0], END_POSITION_Y);
}
};
SwingUtilities.invokeLater(r1);
animateCard(1, END_POSITION_X[1], END_POSITION_Y);
}
}
public void animateCard(int card, int xDest, int yDest) {
cardID = card;
xDestination = xDest;
yDestination = yDest;
totalXDistance = Math.abs(xDestination - START_POSITION_X);
totalYDistance = Math.abs(yDestination - START_POSITION_Y);
animator.start();
}
int cardID;
int xDestination, yDestination, totalXDistance, totalYDistance;
boolean isAnimating = false;
Timer animator = new Timer(15, new ActionListener() {
int startVel = 20;
public void actionPerformed(ActionEvent e) {
double xRelDistance, xAbsDistance, xVel;
int xRealVel;
xAbsDistance = xDestination - xPos.get(cardID);
xRelDistance = xAbsDistance / totalXDistance;
xVel = startVel * xRelDistance;
double yRelDistance, yAbsDistance, yVel;
yAbsDistance = yDestination - yPos.get(cardID);
yRelDistance = yAbsDistance / totalYDistance;
yVel = startVel * yRelDistance;
if (xVel > 0) {
xRealVel = (int) java.lang.Math.ceil(xVel);
} else {
xRealVel = (int) java.lang.Math.floor(xVel);
}
xPos.set(cardID, xPos.get(cardID) + xRealVel);
int yRealVel;
if (xVel > 0) {
yRealVel = (int) java.lang.Math.ceil(yVel);
yPos.set(cardID, yPos.get(cardID) + yRealVel);
} else {
yRealVel = (int) java.lang.Math.floor(yVel);
}
yPos.set(cardID, yPos.get(cardID) + yRealVel);
if ((xPos.get(cardID) == xDestination) && (yPos.get(cardID) == yDestination)) {
isAnimating = false;
} else {
isAnimating = true;
}
repaint();
}
});
}
So all of those variable declared at the class level are shared... Your first call to animateCard will set them and then your second call to animateCard is going to completely overwrite the previous values. You need to change them from class variables to parameters of the animation.
Create a new class AnimationTask that implements ActionListener and save the variables in that class.
E.g.,
class AnimationTask implements ActionListener {
private int cardID;
private int xDest;
private int yDest;
private int totalXDistance;
private int totalYDistance;
public AnimationTask(int cardID, int xDest, int yDest) {
this.cardID = cardID;
this.xDest = xDest;
this.yDest = yDest;
this.totalXDistance = Math.abs(xDestination - START_POSITION_X);
this.totalYDistance = Math.abs(yDestination - START_POSITION_Y);
}
public void actionPerformed(ActionEvent e) {
// do your animation logic...
}
}
and use that custom class in your "animator"
E.g.,
Timer animator = new Timer(15, new AnimationTask(cardId, xDest, yDest);
put
animateCard(1, END_POSITION_X[1], END_POSITION_Y);
inside your run method:
public void run() {
animateCard(0, END_POSITION_X[0], END_POSITION_Y);
}

Categories