Nullpointerexception when adding an array of JButtons to a JFrame - java

I am making a clone of minesweeper with (slightly modified) JButtons. Because there are so many game tiles in minesweeper, I am storing them as an array. When I try and add the buttons to the Frame using a for loop, I get a nullpointerexception on the buttons. The class ButtonObject is extended from the JButton class with just two extra variables and getter/setter methods. What is going wrong?
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Minesweeper extends JFrame implements ActionListener{
JLabel starttitle;
ButtonObject[] minefield;
JFrame frame;
Random r = new Random();
int rand;
JPanel startscreen;
JPanel gamescreen;
int gamesize;
JButton ten;
JButton tfive;
JButton fifty;
GridLayout layout;
public Minesweeper()
{
frame = new JFrame("Minesweeper");
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);;
startscreen = new JPanel();
startScreen();
}
public void startScreen()
{
ten = new JButton("10 x 10");
tfive = new JButton("25 x 25");
fifty = new JButton("50 x 50");
starttitle = new JLabel("Welcome to minesweeper. Click a game size to begin.");
frame.add(startscreen);
startscreen.add(starttitle);
startscreen.add(ten);
startscreen.add(tfive);
startscreen.add(fifty);
ten.addActionListener(this);
tfive.addActionListener(this);
fifty.addActionListener(this);
}
public void initializeGame()
{
minefield = new ButtonObject[gamesize];
for(int i = 0;i<gamesize;i++)
{
minefield[i]=new ButtonObject();
rand = r.nextInt(5);
if(rand==5)
{
minefield[i].setButtonType(true);//this tile is a mine
}
}
}
public void gameScreen()
{
frame.getContentPane().removeAll();
frame.repaint();
initializeGame();
for(int i = 0;i<minefield.length;i++)
{
gamescreen.add(this.minefield[i]);//EXCEPTION HERE
}
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==ten)
{
gamesize = 99;
gameScreen();
}
else if(e.getSource()==tfive)
{
gamesize = 624;
gameScreen();
}
else if(e.getSource()==fifty)
{
gamesize = 2499;
gameScreen();
}
else
{
System.out.println("Fatal error");
}
}
public static void main(String[] args)
{
new Minesweeper();
}
}

Well, you never initialize your gamescreen variable, so that's totally normal you get a NullPointerException at this line.

Related

JCompenents Not Moving With JFrame

I am trying to create a game about war. I am starting off with just creating a single window. I am using swing to create windows. However, when the user tries to resize the JFrame, the elements don't move with the frame. I am resizing the buttons that I use, as well as my JPanel. My code can be seen below:
Main.java:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import Numbers.Numbers;
public class Main implements ActionListener {
static JFrame frame;
static JPanel titlePane;
static JButton playButton;
static JButton explanationButton;
static JPanel explanationPane;
static JButton nextButton;
static JLabel explanationLabel;
static JButton backButton;
static int frameSize = 500;
public Main(boolean run) {
if (run) {
frame = new JFrame("War");
titlePane = new JPanel(null);
playButton = new JButton("PLAY");
explanationButton = new JButton("HOW TO PLAY");
explanationPane = new JPanel(null);
nextButton = new JButton("NEXT");
backButton = new JButton("BACK");
titlePane.setSize(frameSize, frameSize);
titlePane.add(playButton);
playButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
playButton.setBackground(Color.GRAY);
playButton.setForeground(Color.WHITE);
playButton.setVisible(true);
explanationButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/(25/11)), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
explanationButton.setBackground(Color.GRAY);
explanationButton.setForeground(Color.WHITE);
explanationButton.setVisible(true);
explanationPane.setSize(frameSize, frameSize);
explanationPane.add(nextButton);
nextButton.setBounds(225, 50, 50, 15);
nextButton.setBackground(Color.GRAY);
nextButton.setForeground(Color.WHITE);
nextButton.setVisible(true);
backButton.setBounds(225, 450, 50, 15);
backButton.setBackground(Color.GRAY);
backButton.setForeground(Color.WHITE);
backButton.setVisible(true);
frame.setSize(frameSize, frameSize);
frame.add(titlePane);
frame.add(explanationPane);
titlePane.setVisible(false);
explanationPane.setVisible(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
public void switchPane(String pane) {
switch (pane) {
case "title":
titlePane.setVisible(true);
explanationPane.setVisible(false);
break;
case "explanation":
titlePane.setVisible(false);
explanationPane.setVisible(true);
break;
}
}
#Override
public void actionPerformed(ActionEvent event) {
}
public static void main(String[] args) {
Main war = new Main(true);
war.switchPane("title");
while (true) {
if (frame.getX() != frameSize) {
frameSize = frame.getX();
}
else if (frame.getY() != frameSize) {
frameSize = frame.getY();
}
frame.setSize(frameSize, frameSize);
titlePane.setSize(frameSize, frameSize);
explanationPane.setSize(frameSize, frameSize);
playButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
explanationButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/(25/11)), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
}
}
}
Numbers.java:
package Numbers;
public class Numbers {
public static int doubleToInt(double toConvert) {
int toReturn = (int) toConvert;
return toReturn;
}
}
Any help would be appreciated! :)
Please note I am not close to finishing so please ignore the empty method.

JPanel doesn't react to MouseEvents?

I'm trying to create a "Tic Tac Toe" game. I've chosen to create a variation of JPanel to represent each square. The class beneath represents one of 9 panels that together make up my game board.
Now the problem I'm having is that when I click the panel a 'X' should be displayed inside of the panel, but nothing happens. I'd very much appreciate it if someone steered me in the right direction.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TicTacToePanel extends JPanel implements MouseListener {
private boolean isPlayer1Turn = true;
private boolean isUsed = false;
private JLabel ticTacLbl = new JLabel();
public TicTacToePanel() {
setBorder(BorderFactory.createLineBorder(Color.BLACK));
addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
if (!isUsed) {
if (isPlayer1Turn) {
ticTacLbl.setForeground(Color.red);
ticTacLbl.setText("X");
add(ticTacLbl, 0);
isUsed = true;
} else {
ticTacLbl.setForeground(Color.blue);
ticTacLbl.setText("O");
add(ticTacLbl, 0);
isUsed = true;
}
} else {
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, new TicTacToePanel());
}
}
EDIT:
I simply added my label component in the constructor of my TicTacToePanel so that I no longer have to call revalidate() and I'm not adding components during runtime.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TicTacToePanel extends JPanel implements MouseListener{
private boolean isPlayer1Turn = true;
private boolean isUsed = false;
private JLabel ticTacLbl = new JLabel();
public TicTacToePanel(){
add(ticTacLbl, 0);
setBorder(BorderFactory.createLineBorder(Color.BLACK));
addMouseListener(this);
}
public void mouseClicked(MouseEvent e){
}
public void mousePressed(MouseEvent e){
if (!isUsed) {
if (isPlayer1Turn) {
ticTacLbl.setForeground(Color.red);
ticTacLbl.setText("X");
isUsed = true;
} else {
ticTacLbl.setForeground(Color.blue);
ticTacLbl.setText("O");
isUsed = true;
}
}
else{
}
}
public void mouseReleased(MouseEvent e){
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public static void main(String[] args){
JOptionPane.showMessageDialog(null, new TicTacToePanel());
}
}
The GUI constructor:
public TicTacToeGUI(int gameMode){
if(gameMode == 0){
amountOfPanels = 9;
TicTacToePanel[] panelArr = new TicTacToePanel[amountOfPanels];
add(gamePanel, new GridLayout(3, 3));
setPreferredSize(new Dimension(100, 100));
for(int i = 0; i < amountOfPanels; i++){
panelArr[i] = new TicTacToePanel();
gamePanel.add(panelArr[i]);
}
}
else if(gameMode == 1){
amountOfPanels = 225;
TicTacToePanel[] panelArr = new TicTacToePanel[amountOfPanels];
add(gamePanel, new GridLayout(15, 15));
setPreferredSize(new Dimension(500, 500));
for(int i = 0; i < amountOfPanels; i++){
panelArr[i] = new TicTacToePanel();
gamePanel.add(panelArr[i]);
}
}
}
public static void main(String[] args){
JOptionPane.showMessageDialog(null, new TicTacToeGUI(0));
}
}
When you add/remove components at runtime, always call revalidate() afterwards. revalidate() makes the component refresh/relayout.
So just call revalidate() after you add the label and it will work.
If you're goal is to create a Tic Tac Toe game, then you may wish to re-think your current strategy of adding components to the GUI on the fly. Much better would be to create a grid of components, say of JLabel, and place them on the JPanel at program start up. This way you can change the pressed JLabel's text and color, and even its Icon if you want to be fancy during program run without having to add or remove components. For example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class TicTacToePanel extends JPanel {
private static final int ROWS = 3;
private static final int MY_C = 240;
private static final Color BG = new Color(MY_C, MY_C, MY_C);
private static final int PTS = 60;
private static final Font FONT = new Font(Font.SANS_SERIF, Font.BOLD, PTS);
public static final Color X_COLOR = Color.BLUE;
public static final Color O_COLOR = Color.RED;
private JLabel[][] labels = new JLabel[ROWS][ROWS];
private boolean xTurn = true;
public TicTacToePanel() {
setLayout(new GridLayout(ROWS, ROWS, 2, 2));
setBackground(Color.black);
MyMouse myMouse = new MyMouse();
for (int row = 0; row < labels.length; row++) {
for (int col = 0; col < labels[row].length; col++) {
JLabel label = new JLabel(" ", SwingConstants.CENTER);
label.setOpaque(true);
label.setBackground(BG);
label.setFont(FONT);
add(label);
label.addMouseListener(myMouse);
}
}
}
private class MyMouse extends MouseAdapter {
#Override // override mousePressed not mouseClicked
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel) e.getSource();
String text = label.getText().trim();
if (!text.isEmpty()) {
return;
}
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// information to help check for win
int chosenX = -1;
int chosenY = -1;
for (int x = 0; x < labels.length; x++) {
for (int y = 0; y < labels[x].length; y++) {
if (labels[x][y] == label) {
chosenX = x;
chosenY = y;
}
}
}
// TODO: check for win here
xTurn = !xTurn;
}
}
private static void createAndShowGui() {
TicTacToePanel mainPanel = new TicTacToePanel();
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Image did not fresh in Frame on Mouse Click In Java

First Time three random images shown on Jframe from three diffrent arrays.
even MouseClicked Method triggered but images does not refresh in Frame.
I want to refresh three random images each time i click on Frame.
Please help
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.*;
public class Cards extends JFrame implements MouseListener {
public static void main(String[] args) {
JFrame frame = new Cards();
frame.setTitle("Cards");
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
new Cards();
}
public Cards() {
this.getContentPane().addMouseListener(this);
cards1();
cards2();
cards3();
}
public void cards1() {
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void cards2() {
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images1//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void cards3() {
// this.getContentPane().addMouseListener(this);
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images2//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
// Labels with gridLayout
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void mouseClicked(MouseEvent e) {
System.out.println("The frame was clicked.");
new Cards();
}
public void mouseEntered(MouseEvent e) {
System.out.println("The mouse entered the frame.");
}
public void mouseExited(MouseEvent e) {
System.out.println("The mouse exited the frame.");
}
public void mousePressed(MouseEvent e) {
System.out.println("The left mouse button was pressed.");
}
public void mouseReleased(MouseEvent e) {
System.out.println("The left mouse button was released.");
}
}
I'm sorry, but I'm confused by your code. For one thing your cards1(), cards2() and cards3() methods look to be all the very same, and if so, why 3 different methods? Why not just one method? In those methods you appear to be trying to add JLabels repeatedly. Are you trying to add many many JLabels to the GUI? Or are you simply trying to display 3 images that change randomly on mouse action?
I would recommend structuring things a bit differently:
If possible, read all necessary images in once in your class's constructor, put the images into ImageIcons and then add them to an ArrayList or several ArrayLists if need be.
Don't add new JLabels each time a mouseClick occurs.
Create a JPanel give it a GridLayout and in your class constructor add to it three JLabels that are either instance fields or in an array or ArrayList.
Add this JPanel to your JFrame.
Add a MouseListener to each JLabel
in that MouseListener's mousePressed(MouseEvent e) method (not mouseClicked) randomize your number and use that number to call setIcon(...) on the JLabel source, obtained by calling getSource() on your MouseEvent parameter.
For example:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomImages extends JPanel {
private static final int LABEL_COUNT = 3;
private Random random = new Random();
public RandomImages() {
setLayout(new GridLayout(1, 3));
for (int i = 0; i < LABEL_COUNT; i++) {
final List<Icon> iconList = new ArrayList<>();
// TODO: get images for the ith list
// and fill iconList with ImageIcons from the first grouping
// create JLabel and give it the first Icon from the List above
final JLabel label = new JLabel(iconList.get(0));
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// get random number from random object using iconList.size()
// get random Icon from list
// set label's icon via setIcon(...)
}
});
// add to GUI
add(label);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RandomImages());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Concrete example 2:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomChessMen extends JPanel {
// for this example I get a sprite sheet that holds several sprite images in it
// the images can be found here: http://stackoverflow.com/questions/19209650
private static final String IMAGE_PATH = "http://i.stack.imgur.com/memI0.png";
private static final int LABEL_COUNT = 2;
private static final int ICON_COLUMNS = 6;
private Random random = new Random();
public RandomChessMen() throws IOException {
URL url = new URL(IMAGE_PATH);
BufferedImage largeImg = ImageIO.read(url);
setLayout(new GridLayout(1, 0));
// break down large image into its constituent sprites and place into ArrayList<Icon>
int w = largeImg.getWidth() / ICON_COLUMNS;
int h = largeImg.getHeight() / LABEL_COUNT;
for (int i = 0; i < LABEL_COUNT; i++) {
final List<Icon> iconList = new ArrayList<>();
int y = (i * largeImg.getHeight()) / LABEL_COUNT;
// get 6 icons out of large image
for (int j = 0; j < ICON_COLUMNS; j++) {
int x = (j * largeImg.getWidth()) / ICON_COLUMNS;
// get subImage
BufferedImage subImg = largeImg.getSubimage(x, y, w, h);
// create ImageIcon and add to list
iconList.add(new ImageIcon(subImg));
}
// create JLabel
final JLabel label = new JLabel("", SwingConstants.CENTER);
int eb = 40;
label.setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
// get random index for iconList
int randomIndex = random.nextInt(iconList.size());
Icon icon = iconList.get(randomIndex); // use index to get random Icon
label.setIcon(icon); // set label's icon
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
Icon secondIcon = label.getIcon();
// so we don't repeat icons
while (label.getIcon() == secondIcon) {
int randomIndex = random.nextInt(iconList.size());
secondIcon = iconList.get(randomIndex);
}
label.setIcon(secondIcon);
}
});
// add to GUI
add(label);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
frame.getContentPane().add(new RandomChessMen());
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have made these changes to your code:
Instead of having three methods cards1() cards2() cards3(), i have just made one cards() method.
Everytime you click on the frame, three random images get loaded.
I have set every image inside a JLabel in order to make it easy to update it.
The code below works perfectly according to your needs.
package example;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class Cards extends JFrame implements MouseListener {
JPanel subPanel1;
JLabel label1, label2, label3;
static ImageIcon[] images ;
static Random ran ;
static int[] threeRandoms;
public Cards() {
super("Cards");
subPanel1 = new JPanel();
// Set up first subpanel
subPanel1.setPreferredSize (new Dimension(400, 400));
//subPanel1.setBackground (Color.cyan);
label1 = new JLabel ("image 1",SwingConstants.CENTER);
label2 = new JLabel ("image 2", SwingConstants.LEFT);
label3 = new JLabel ("image 3", SwingConstants.CENTER);
subPanel1.add (label1);
subPanel1.add (label2);
subPanel1.add (label3);
add(subPanel1);
addMouseListener(this);
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
System.out.println("Success.....");
}
public void cards() {
for (int i = 0; i < threeRandoms.length; i++)
threeRandoms[i] = ran.nextInt(3);
label1.setIcon(images[threeRandoms[0]]);
label2.setIcon(images[threeRandoms[1]]);
label3.setIcon(images[threeRandoms[2]]);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouseClicked");
cards();
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("mouseEntered");
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("mouseExited");
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased");
}
public static void loadImages(){
images = new ImageIcon[4];
ran = new Random();
threeRandoms = new int[3];
for (int i = 1; i <= images.length; i++) {
images[i-1] = new ImageIcon("Drawables//Images//" + i + ".png");
}
}
public static void main(String[] args) {
loadImages();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Cards();
}
});
}
}

Java - adding JButton array to JFrame

I am trying to add a 2D JButton array to a JFrame, I don't get any errors, just the JButtons don't show up.
Creating the JButtons:
public class TTTGrid {
private static JFrame frame;
private static int[][] coords;
private static int width, height;
public TTTGrid(JFrame frame,int[][] coords, int width, int height){
this.frame = frame;
this.coords = coords;
this.width = width;
this.height = height;
}
static JButton map[][] = new JButton[3][3];
public void Draw(){
for(int i = 0; i<coords.length; i++){
for(int j = 0; j<coords[i].length; j++){
map[i][j] = new JButton();
map[i][j].setBounds(i*100, j*100, width, height);
frame.add(map[i][j]);
}
}
}
}
Where the draw method is called:
public class TTTthread extends TTT implements Runnable {
int[][] map = new int[3][3];
TTTGrid grid = new TTTGrid(frame, map, 100, 100);
#Override
public void run() {
try {
while (true) {
grid.Draw();
Thread.sleep(20);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
If your code is running like I think it's running, you appear to be trying to add 9 JButtons to your GUI 50 times a second! That's a heck of a lot of buttons -- are you sure that this is what you want to be doing? Your code also runs far afoul of Swing threading rules by making Swing calls (a lot of Swing calls!) off of the Swing event thread.
Your main solution is likely to
Add your 9 JButtons to a JPanel that uses a GridLayout(3, 3)
Do this only once not 50 times a second
Then add that JPanel to your GUI, BorderLayout.CENTER and to be sure not to use null layouts.
Not try to set the bounds, size or locations of these JButtons, but rather to let the layout managers to the work
Get rid of that while loop and instead change your code to be more event-driven using Swing's event driven model.
Strive to use mostly non-static variables and methods so that your classes become true OOPS-compliant classes, allowing them to take advantage of the benefits of OOPS programming, including reducing program complexity and interconnectedness (reduce coupling).
For example
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class MyTttFoo extends JPanel {
// it's OK for constants to be static
private static final long serialVersionUID = 1L;
private static final int ROWS = 3;
// use a larger Font to make buttons larger
private static final Font BTN_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 60);
private static final String BLANK = " ";
private static final String X = "X";
private static final String O = "O";
// but not most variables
private JButton[][] buttonGrid = new JButton[ROWS][ROWS];
public MyTttFoo() {
setBackground(Color.black);
// use layout managers to help you create your GUI
setLayout(new GridLayout(ROWS, ROWS, 1, 1));
ActionListener btnListener = new ButtonListener();
// create your buttons and add them only **once**
for (int row = 0; row < buttonGrid.length; row++) {
for (int col = 0; col < buttonGrid[row].length; col++) {
JButton button = new JButton(BLANK);
button.setFont(BTN_FONT);
button.addActionListener(btnListener);
add(button); // add button to a gridlayout using component
buttonGrid[row][col] = button; // and assign into the array
}
}
}
private class ButtonListener implements ActionListener {
private boolean xTurn = true;
#Override
public void actionPerformed(ActionEvent e) {
AbstractButton btn = (AbstractButton) e.getSource();
String txt = btn.getText();
if (txt.equals(BLANK)) {
if (xTurn) {
btn.setText(X);
} else {
btn.setText(O);
}
xTurn = !xTurn;
}
}
}
private static void createAndShowGui() {
MyTttFoo mainPanel = new MyTttFoo();
JFrame frame = new JFrame("MyTttFoo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Stack Oveflow error

I keep getting a stack overflow error when I run this short program I made! please help! Right now all it's supposed to do is take the users input and print their position (in X and Y coordinates). I'm not sure what Stack overflow error is or how to fix it.
import java.awt.*;
import javax.swing.*;
public class ExplorerPanel extends JFrame {
ExplorerEvent prog = new ExplorerEvent(this);
JTextArea dataa = new JTextArea(15, 20);
JTextField datain = new JTextField(20);
JButton submit = new JButton("Submit");
JTextField errors = new JTextField(30);
public ExplorerPanel() {
super("Explorer RPG");
setLookAndFeel();
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_…
BorderLayout bord = new BorderLayout();
setLayout(bord);
JPanel toppanel = new JPanel();
toppanel.add(dataa);
add(toppanel, BorderLayout.NORTH);
JPanel middlepanel = new JPanel();
middlepanel.add(datain);
middlepanel.add(submit);
add(middlepanel, BorderLayout.CENTER);
JPanel bottompanel = new JPanel();
bottompanel.add(errors);
add(bottompanel, BorderLayout.SOUTH);
dataa.setEditable(false);
errors.setEditable(false);
submit.addActionListener(prog);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.nimbus.NimbusLo…
);
} catch (Exception exc) {
// ignore error
}
}
public static void main(String[] args) {
ExplorerPanel frame = new ExplorerPanel();
}
}
public class ExplorerEvent implements ActionListener, Runnable {
ExplorerPanel gui;
Thread playing;
String command;
String gamedata;
ExplorerGame game = new ExplorerGame();
public ExplorerEvent(ExplorerPanel in) {
gui = in;
}
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("Submit")) {
startPlaying();
}
}
void startPlaying() {
playing = new Thread(this);
playing.start();
}
void stopPlaying() {
playing = (null);
}
void clearAllFields() {
gui.dataa.setText("");
}
public void run() {
Thread thisThread = Thread.currentThread();
while (playing == thisThread) {
// Game code
game.Game();
}
}
}
public class ExplorerGame {
ExplorerPanel gui = new ExplorerPanel();
String command;
int x = 1;
int y = 1;
public void Game() {
command = gui.submit.getText().toLowerCase();
if (command.equals("east")) {x--;}
else if (command.equals("south")) {y--;}
else if (command.equals("west")) {x++;}
else if (command.equals("north")) {y++;}
System.out.println(x + y);
}
}
In ExplorerGame, you have declared: -
ExplorerPanel gui = new ExplorerPanel();
then, in ExplorerPanel: -
ExplorerEvent prog = new ExplorerEvent(this);
and then again, in ExplorerEvent: -
ExplorerGame game = new ExplorerGame();
This will fill the Stack with recursive creation of objects.
ExplorerGame -> ExplorerPanel -> ExplorerEvent --+
^ |
|____________________________________________|
You want to solve the Issue?
I'll Suggest you: -
Throw away the code, and re-design your application. Having a cyclic dependency in your application is a big loop hole, showing a very poor design.

Categories