I am trying to make a basic map where pressing a button moves a character.
I am using Netbeans and so far it's going smoothly! Except for trying to remove a JLabel from a JPanel and then add a new JLabel to it.
Here is my full code:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class startMap extends JFrame {
public int locX = 1;
public int locY = 1;
ImageIcon tile = new ImageIcon("src/tile.png");
JLabel tileLabel = new JLabel(tile);
ImageIcon berry = new ImageIcon("src/berry.png");
JLabel berryLabel = new JLabel(berry);
ImageIcon blank = new ImageIcon("src/blank.png");
JLabel blankLabel = new JLabel(blank);
JLabel testL = new JLabel("LOL");
JPanel[][] map = new JPanel[7][7];
public startMap() {
setBackground(Color.BLACK);
setFocusable(true);
keyHandler kh = new keyHandler();
addKeyListener(kh);
mapGUI();
}
public void mapGUI() {
JPanel mainP = new JPanel();
mainP.setBackground(Color.BLACK);
mainP.setLayout(new FlowLayout());
for (int x = 0; x < 7; x++) {
for (int i = 0; i < 7; i++) {
map[x][i] = new JPanel();
System.out.println("1");
blankLabel = new JLabel(blank);
map[x][i].setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
map[x][i].add(blankLabel);
}
}
for (int x = 1; x < 6; x++) {
for (int i = 1; i < 6; i++) {
System.out.println("2");
map[x][i].removeAll();
revalidate();
repaint();
tileLabel = new JLabel(tile);
map[x][i].add(tileLabel);
revalidate();
repaint();
}
}
System.out.println("3");
map[locX][locY].removeAll();
revalidate();
repaint();
map[locX][locY].add(berryLabel);
revalidate();
repaint();
for (int x = 0; x < 7; x++) {
for (int i = 0; i < 7; i++) {
mainP.add(map[x][i]);
}
}
add(mainP);
}
#Override
public void paint(Graphics g) {
super.paint(g);
}
private class keyHandler extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
locY+=1;
map[locX][locY].removeAll();
revalidate();
repaint();
map[locX][locY].add(berryLabel);
revalidate();
repaint();
}
}
}
}
Here is what changes the squares when the user clicks Right.
Here is the KeyAdapter code:
private class keyHandler extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
locY+=1;
map[locX][locY].removeAll();
revalidate();
repaint();
map[locX][locY].add(berryLabel);
revalidate();
repaint();
}
}}
NOTE: the system out is just a debugging method I use to check what's being called when.
So when I run it looks like this
Move to the right and revalidate $ repaint:
Why does the box located in 1,1 go to being gray?
Help figuring out how to make the boxes stay with a white square instead of turning back to gray.
----------------------------SSCCE----------------------------------
Use the full code above
and this is the main class:
import javax.swing.*;
public class TestGame extends JFrame {
public static void main(String[] args) {
startMap sm = new startMap();
sm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sm.setVisible(true);
sm.setSize(380,415);
sm.setResizable(false);
}
}
Fixed Version:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class startMap extends JFrame {
public int locX = 1;
public int locY = 1;
ImageIcon tile = new ImageIcon("src/tile.png");
JLabel tileLabel = new JLabel(tile);
ImageIcon berry = new ImageIcon("src/berry.png");
JLabel berryLabel = new JLabel(berry);
ImageIcon blank = new ImageIcon("src/blank.png");
JLabel blankLabel = new JLabel(blank);
JLabel testL = new JLabel("LOL");
JPanel[][] map = new JPanel[7][7];
public startMap() {
setBackground(Color.BLACK);
setFocusable(true);
keyHandler kh = new keyHandler();
addKeyListener(kh);
mapGUI();
}
public void mapGUI() {
JPanel mainP = new JPanel();
mainP.setBackground(Color.BLACK);
mainP.setLayout(new FlowLayout());
for (int x = 0; x < 7; x++) {
for (int i = 0; i < 7; i++) {
map[x][i] = new JPanel();
System.out.println("1");
blankLabel = new JLabel(blank);
map[x][i].setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
map[x][i].add(blankLabel);
}
}
for (int x = 1; x < 6; x++) {
for (int i = 1; i < 6; i++) {
System.out.println("2");
map[x][i].removeAll();
tileLabel = new JLabel(tile);
map[x][i].add(tileLabel);
revalidate();
repaint();
}
}
System.out.println("3");
map[locX][locY].removeAll();
map[locX][locY].add(berryLabel);
revalidate();
repaint();
for (int x = 0; x < 7; x++) {
for (int i = 0; i < 7; i++) {
mainP.add(map[x][i]);
}
}
add(mainP);
}
#Override
public void paint(Graphics g) {
super.paint(g);
}
private class keyHandler extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
berryLabel = new JLabel(berry); //THIS
tileLabel = new JLabel(tile); //And THIS had to be RE initialized idk why.
map[locX][locY].removeAll();
map[locX][locY].add(tileLabel);
locY += 1;
map[locX][locY].removeAll();
map[locX][locY].add(berryLabel);
revalidate();
repaint();
}
}
}
}
Should be called after adding / removing
revalidate();
repaint();
Don't call repaint() from paint()
Related
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'm trying to make a checkers game and and all seams well so far, but when I hover over the button the graphics glitch out and I don't know why. Also it adds a lot of buttons to the top and when I move it around (resize) it adds more. It also adds more when I press any green buttons. And they are very tiny buttons at the top and I don't see where they pop up in my code.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
private JButton Green;
private JButton Blue;
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Checkers");
JPanel contentPane = new JPanel();
GameListener listener = new GameListener() {
#Override
public void gameWasCompleted() {
contentPane.repaint();
}
#Override
public void startNewGame() {
System.out.println("button worked");
contentPane.repaint();
}
};
MainPane mainPane = new MainPane();
mainPane.setGameListener(listener);
contentPane.add(mainPane);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface GameListener {
void gameWasCompleted();
void startNewGame();
}
public class MainPane extends JPanel implements MouseListener {
private GameListener gameListener;
public MainPane() {
addMouseListener(this);
}
public void setGameListener(GameListener gameListener) {
this.gameListener = gameListener;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xshift;
int yshift = 0;
g.setColor(new Color(0, 0, 0));
for (int i = 0; i < 4; i++) {
xshift = 125;
for (int j = 0; j < 4; j++) {
g.fillRect(xshift, yshift, 125, 125);
xshift += 250;
}
xshift = 0;
yshift += 125;
for (int k = 0; k < 4; k++) {
g.fillRect(xshift, yshift, 125, 125);
xshift += 250;
}
yshift += 125;
}
initalprnt(g);
}
protected void initalprnt(Graphics g) {
int xshift = 125;
int yshift = 0;
g.setColor(new Color(0, 100, 0));
for (int i = 0; i < 3; i++) {
if (i == 2) {
xshift = 125;
}
for (int j = 0; j < 4; j++) {
g.fillOval(xshift, yshift, 125, 125);
Green = new JButton();
Green.setBackground(new Color(0, 100, 0, 0));
Green.setBounds(xshift, yshift, 125, 125);
add(Green);
xshift += 250;
}
xshift = 0;
yshift += 125;
}
yshift += 250;
g.setColor(new Color(0, 0, 100));
for (int k = 0; k < 3; k++) {
if (k == 2) {
xshift = 0;
}
for (int j = 0; j < 4; j++) {
g.fillOval(xshift, yshift, 125, 125);
Blue = new JButton();
Blue.setBackground(new Color(0, 0, 100, 0));
Blue.setBounds(xshift, yshift, 125, 125);
add(Blue);
xshift += 250;
}
xshift = 125;
yshift += 125;
}
buttons();
}
public void buttons() {
Green.addActionListener(e -> {
System.out.println("this does something");
gameListener.startNewGame();
});
Blue.addActionListener(e -> {
System.out.println("this did something");
gameListener.startNewGame();
});
}
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
}
Basic rule of thumb, do not, under any circumstances, modify the state of the component (or any other component) during a paint pass. This can (and probably will) cause the component to be rescheduled for another paint pass and you'll end up in an infinite loop.
There are so many ways you "might" achieve this, for example, you could use JButtons in a GridLayout.
Then all you need to is devise an appropriate model and delegation/observer workflow to keep the UI in sync with the model
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
BoardPane boardPane = new BoardPane();
boardPane.setBoardListener(new BoardListener() {
#Override
public void cellWasSelected(Point p) {
System.out.println("Cell selected " + p);
}
});
frame.add(boardPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface BoardListener {
public void cellWasSelected(Point p);
}
public class BoardPane extends JPanel {
private Map<Point, JButton> cells = new HashMap<>();
private BoardListener boardListener;
public BoardPane() {
int gridSize = 8 * 8;
setLayout(new GridLayout(8, 8));
int index = 0;
for (int row = 0; row < 8; row++) {
int xPos = (row % 2 == 0) ? gridSize : 0;
for (int col = 0; col < 8; col++) {
index++;
JButton btn = new JButton();
btn.setOpaque(true);
btn.setFocusPainted(false);
btn.setBorderPainted(false);
// I'd prefer to rely on something like
// an image, such as an empty image for
// cells which are empty
btn.setPreferredSize(new Dimension(100, 100));
if (index % 2 == 0) {
btn.setBackground(Color.BLACK);
btn.setForeground(Color.WHITE);
} else {
btn.setBackground(Color.WHITE);
btn.setForeground(Color.BLACK);
}
Point p = new Point(col, row);
btn.putClientProperty("cell", p);
cells.put(p, btn);
add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
BoardListener listener = getBoardListener();
if (listener == null) {
return;
}
Point p = (Point)btn.getClientProperty("cell");
listener.cellWasSelected(p);
}
});
}
index++;
}
}
public void setBoardListener(BoardListener boardListener) {
this.boardListener = boardListener;
}
public BoardListener getBoardListener() {
return boardListener;
}
}
}
Generally, I would use either a completely component based or custom painting based solution and avoid mixing the two.
Remember, the board should be focused only on what the board needs to do and shouldn't be doing anything else. This is the point of "separation of concerns/responsibility"
A far more complex solution might use a custom layout to manage components on top of a custom painted board, but that is, simply way beyond the scope of the question or your abilities at this time
I am making a simple maze game, and am trying to make a main menu for it. Basically, whenever a JButton is pressed, an ActionListener is called, and creates a new window with the game inside of it. inside the game, there is a KeyListener so that you can move around with the arrow keys. However, when I run it, the arrow keys do not work, and the button stays pressed. Here is the code for the MainMenu:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
public class MainMenu extends JFrame
{
private int timer;
private JLabel Timer;
public MainMenu(String title, int width, int height){
JButton maze1 = new JButton("Maze 1");
JButton maze2 = new JButton("Maze 2");
JButton maze3 = new JButton("Maze 3");
JButton maze4 = new JButton("Maze 4");
JButton maze5 = new JButton("Maze 5");
JLabel instructions = new JLabel();
instructions.setText("Pick a maze!");
Timer = new JLabel();
Timer.setBounds(0, 150, 220, 20);
Timer.setText("0.0");
maze1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
try{playMaze(1);}catch(FileNotFoundException e){}
}
});
maze2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
try{playMaze(2);}catch(FileNotFoundException e){}
}
});
maze3.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
try{playMaze(3);}catch(FileNotFoundException e){}
}
});
maze4.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
try{playMaze(4);}catch(FileNotFoundException e){}
}
});
maze5.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
try{playMaze(5);}catch(FileNotFoundException e){}
}
});
add(instructions);
add(maze1);
add(maze2);
add(maze3);
add(maze4);
add(maze5);
setTitle(title);
setLayout(new FlowLayout());
setSize(width, height);
timer = 0;
}
public void playMaze(int i) throws FileNotFoundException{
MazeCreator creator = new MazeCreator();
creator.createMaze("MAZE" + i + ".txt");
MazeRunner runner = new MazeRunner(creator.getMaze(), 0, 5, timer);
runner.run();
timer = runner.getTime();
Timer.setText("" + timer/10.0);
}
}
The MazeRunner:
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class MazeRunner implements Runnable
{
private JFrame frame;
private Canvas canvas;
private BufferStrategy bufferStrategy;
private String[][] maze;
private int x;
private int y;
private boolean win;
private int timer;
public MazeRunner(String[][] Maze, int Y, int X, int t){
frame = new JFrame("Maze Game");
JPanel panel = (JPanel) frame.getContentPane();
panel.setPreferredSize(new Dimension(220, 250));
panel.setLayout(null);
canvas = new Canvas();
canvas.setBounds(0, 0, 220, 250);
canvas.setIgnoreRepaint(true);
panel.add(canvas);
canvas.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent evt) {
move(evt);
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
canvas.createBufferStrategy(2);
bufferStrategy = canvas.getBufferStrategy();
canvas.requestFocus();
maze = Maze;
x = X;
y = Y;
maze[y][x] = "#";
win = false;
timer = t;
}
public boolean checkWin(){return win;}
public void run(){
while(!win){
Paint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
timer++;
}
maze[y][x] = "#";
Paint();
try{Thread.sleep(1000);}catch(InterruptedException e){}
frame.dispose();
}
public void move(KeyEvent evt) {
switch (evt.getKeyCode()) {
case KeyEvent.VK_DOWN:
moveDown();
break;
case KeyEvent.VK_UP:
moveUp();
break;
case KeyEvent.VK_LEFT:
moveLeft();
break;
case KeyEvent.VK_RIGHT:
moveRight();
break;
}
}
public void moveUp(){
maze[y][x] = "-";
if(!(y > 0)){
}else if(maze[y - 1][x].equals("*")){
}else if(maze[y - 1][x].equals("#")){
y -= 1;
win = true;
}else{
y -= 1;
}
maze[y][x] = "#";
}
public void moveDown(){
maze[y][x] = "-";
if(!(y < 10)){
}else if(maze[y + 1][x].equals("*")){
}else if(maze[y + 1][x].equals("#")){
y += 1;
win = true;
}else{
y += 1;
}
maze[y][x] = "#";
}
public void moveLeft(){
maze[y][x] = "-";
if(!(x > 0)){
}else if(maze[y][x - 1].equals("*")){
}else if(maze[y][x - 1].equals("#")){
x -= 1;
win = true;
}else{
x -= 1;
}
maze[y][x] = "#";
}
public void moveRight(){
maze[y][x] = "-";
if(!(x < 10)){
}else if(maze[y][x + 1].equals("*")){
}else if(maze[y][x + 1].equals("#")){
x += 1;
win = true;
}else{
x += 1;
}
maze[y][x] = "#";
}
public void printMaze(){
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
for(int i = 0; i < 11; i++){
for(int e = 0; e < 11; e++){
System.out.print(maze[i][e] + " ");
}
System.out.println();
}
}
public void Paint() {
Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
g.clearRect(0, 0, 500, 500);
Paint(g);
bufferStrategy.show();
}
protected void Paint(Graphics2D g) {
for(int i = 0; i < 11; i++){
for(int e = 0; e < 11; e++){
if(maze[i][e].equals("*")){
g.setColor(Color.BLACK);
g.fillRect(e*20, i*20, 20, 20);
}else if(maze[i][e].equals("#")){
g.setColor(Color.RED);
g.fillOval(e*20, i*20, 20, 20);
}else if(maze[i][e].equals("#")){
g.setColor(Color.BLUE);
g.fillRect(e*20, i*20, 20, 20);
}
}
}
g.setColor(Color.BLACK);
g.drawString("" + (timer / 10.0), 190, 240);
if(win){
g.setFont(new Font("Dialouge", Font.BOLD, 20));
g.drawString("YOU WIN!", 10, 240);
}
}
public String mazeToString(int y){
String toString = "";
for(int e = 0; e < 11; e++){
toString += maze[y][e] + " ";
}
return toString;
}
public int getTime(){return timer;}
}
And the MazeCreator:
import java.util.*;
import java.io.*;
public class MazeCreator
{
private String[][] maze;
private int xPos;
private int yPos;
private File file;
private Scanner input;
public MazeCreator(){
maze = new String[11][11];
}
public String[][] getMaze(){return maze;}
public void createMaze(String File) throws FileNotFoundException{
input = new Scanner(new File("C:/Users/Owner/Maze/" + File));
for(int i = 0; i < 11; i++){
for(int e = 0; e < 11; e++){
maze[i][e] = input.next();
//System.out.print(maze[i][e] + " ");
}
input.nextLine();
//System.out.println();
}
}
}
Any help that anyone could give would be great.
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);
}
});
}
}
I am a beginner programmer and I am trying to make a simple 2D game, Breakout. I have the logic for the game itself working but I am having trouble with getting the buttons to work with the game. I added a start and pause button to the top of the screen but whenever I pressed one of these buttons, the paddle at the bottom of the screen cannot move.
When I take out the buttons the game runs perfectly.
Any help would be greatly appreciated! Thank you in advance.
Below is the code for my game. I only included the Breakout class because this was were I ran into trouoble.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.TimerTask;
public class Breakout extends JPanel implements KeyListener, ActionListener
{
boolean rightPressed;
boolean leftPressed;
boolean upPressed;
boolean downPressed;
boolean inGame;
int width = 1450;
int height = 900;
Timer tm = new Timer(5, this);
int numRows =5;
int numCols = 8;
int numBricks = 40;
int mouseX;
int mouseY;
Paddle paddle = new Paddle(width/2, height-40);
Ball ball = new Ball();
//BrickArray brick = new BrickArray(numRows, numCols, width/numCols, (height-100)/numRows);
Brick[][] bricks = new Brick[8][5];
JButton start = new JButton("Start");
JButton pause = new JButton("Pause");
JButton reset = new JButton("Reset");
JButton exit = new JButton("Exit");
JButton help = new JButton("Help");
public Breakout()
{
setDoubleBuffered(true);
//tm.start();
addKeyListener(this);
setFocusable(true);
add(start);
start.addActionListener(new StartAction());
add(pause);
pause.addActionListener(new PauseAction());
add(reset);
add(exit);
add(help);
ball.setMaxX(width);
ball.setMaxY(height);
ball.setWidth(width);
ball.setHeight(height);
ball.setX(width/2); //width/2
ball.setY(height/2); //height
paddle.setMaxX(width-paddle.getWidth());
int k=0;
//row 1
for(int a=0; a<bricks.length; a++)
{
bricks[a][0]=new Brick(120,40);
bricks[a][0].setX(a*180);
bricks[a][0].setY(50);
//System.out.println(k + ": " + a*80);
}
//row 2
for(int b=0; b<bricks.length; b++)
{
bricks[b][1]=new Brick(120,40);
bricks[b][1].setX(b*180);
bricks[b][1].setY(100);
}
//row 3
for(int c=0; c<bricks.length; c++)
{
bricks[c][2]=new Brick(120,40);
bricks[c][2].setX(c*180);
bricks[c][2].setY(150);
}
//row 4
for(int d=0; d<bricks.length; d++)
{
bricks[d][3]=new Brick(120,40);
bricks[d][3].setX(d*180);
bricks[d][3].setY(200);
}
for(int e=0; e<bricks.length; e++)
{
bricks[e][4]=new Brick(120,40);
bricks[e][4].setX(e*180);
bricks[e][4].setY(250);
}
}
public void actionPerformed(ActionEvent e)
{
tm.setRepeats(true);
if(rightPressed)
{
paddle.setX(paddle.getX()+5);
//System.out.println("Pressed");
}
if(leftPressed)
paddle.setX(paddle.getX()-5);
/*if(upPressed)
y--;
if(downPressed)
y++;*/
ball.checkCollision(paddle);
for(int i=0; i<bricks.length; i++)
{
for(int j=0; j<bricks[i].length; j++)
{
if(ball.checkCollision(bricks[i][j]))
{
bricks[i][j].destroy();
//System.out.println(bricks[i][j].isDestroyed());
numBricks--;
ball.move();
repaint();
}
}
}
//ball.checkCollision(brick);
ball.move();
repaint();
}
public void keyPressed(KeyEvent e)
{
int c = e.getKeyCode();
if(c == KeyEvent.VK_LEFT)
{
leftPressed=true;
}
/*if(c == KeyEvent.VK_UP)
{
upPressed=true;
}*/
if(c == KeyEvent.VK_RIGHT)
{
rightPressed=true;
//System.out.println("Pressed");
}
/*if(c == KeyEvent.VK_DOWN)
{
downPressed=true;
}*/
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
int c = e.getKeyCode();
if(c == KeyEvent.VK_LEFT)
{
leftPressed=false;
}
if(c == KeyEvent.VK_UP)
{
upPressed=false;
}
if(c == KeyEvent.VK_RIGHT)
{
rightPressed=false;
}
if(c == KeyEvent.VK_DOWN)
{
downPressed=false;
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int a=0; a<bricks.length; a++)
{
g.setColor(Color.RED);
bricks[a][0].paintComponent(g);
}
for(int b=0; b<bricks.length; b++)
{
g.setColor(Color.ORANGE);
bricks[b][1].paintComponent(g);
}
for(int c=0; c<bricks.length; c++)
{
g.setColor(Color.YELLOW);
bricks[c][2].paintComponent(g);
}
for(int d=0; d<bricks.length; d++)
{
g.setColor(Color.GREEN);
bricks[d][3].paintComponent(g);
}
for(int e=0; e<bricks.length; e++)
{
g.setColor(Color.BLUE);
bricks[e][4].paintComponent(g);
}
ball.paintComponent(g);
paddle.paintComponent(g);
g.setColor(Color.BLACK);
g.drawString("Bricks left: " + numBricks, 10, 10);
}
public static void main(String[] args)
{
Breakout obj = new Breakout();
JFrame jf = new JFrame();
jf.setTitle("Breakout");
jf.setSize(1450,900);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(obj);
}
class StartAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
tm.start();
System.out.println("Start");
}
}
class PauseAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
tm.stop();
System.out.println("Pause");
}
}
}
I don't have the other classes implemented so I cannot confirm if this will work.
start.setFocusable(false);
pause.setFocusable(false);
Alternatively
start.addKeyListener(this);
pause.addKeyListener(this);