Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Stuck on a problem that requires grabbing a boolean variable from another class.
I have the following for-loop, boolean and if-else statements
import java.awt.*;
import javax.swing.*;
import java.awt.Color.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.Random;
public class Checkers extends JFrame
{
Random random = new Random();
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private int i;
private int score;
private JPanel pane = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
private JPanel pane2 = new JPanel();
private JPanel pane3 = new JPanel();
private JButton btn1 = new JButton("Play A Game");
private JButton btn2 = new JButton("Exit");
private JButton btn3 = new JButton("Easy");
private JButton btn4 = new JButton("Intermediate");
private JButton btn5 = new JButton("Difficult");
private JLabel lbl1 = new JLabel ("score: " + score);
private JLabel gameLost = new JLabel("You lose! You got: " + score + " points");
private JButton btnRestart = new JButton("Restart");
private MyPanel [] panel = new MyPanel[NUM];
private Color col1 = Color.RED;
private Color col2 = Color.WHITE;
private Color col3 = Color.GREEN;
private Color tempColor;
private boolean isPanelDisabled;
//Starts the checkers GUI, calling the constructor below this.
public static void main(String[] args){
new Checkers();
}
//Sets the dimensions of the GUI, visibility, background color and
//contents via the setBoard();
public Checkers()
{
super("Checkers");
setSize(600,600);
setVisible(true);
setBackground(Color.BLACK);
setBoard();
}
//Makes the grid, contains a conditional boolean, adds the panels to grid based on i value.
//sets Colours accordingly
public void setBoard()
{
boolean isPanelDisabled = false;
for (int i = 0; i < panel.length; i++) {
panel[i] = new MyPanel(this);
pane.add(panel[i]);
if (i % COLS == 0) {
tempColor = col1;
}
if (i == 9 || i <8) {
panel[i].setBackground(col1);
}
if(i == 8){
isPanelDisabled = true;
panel[i].setBackground(col3);
}
}
//pane background colour and the size of this pane.
pane.setBackground(Color.BLACK);
pane.setPreferredSize(new Dimension(300,300));
//pane background colour and size of this pane.
pane2.setBackground(Color.white);
pane2.setPreferredSize(new Dimension(300,300));
//directions on the board where these panes appear.
add(pane, BorderLayout.WEST);
add(pane2, BorderLayout.EAST);
pane2.add(lbl1);
pane2.add(btnRestart);
btnRestart.addActionListener( e -> restartBoard());
pane2.setLayout(new BoxLayout(pane2, BoxLayout.PAGE_AXIS));
}
//increments the score for the user based on current points.
public void incrementScore(){
if (score != 5){
score++;
lbl1.setText("Score: " + Integer.toString(score));
}
else if(score == 5){
lbl1.setText("Congratulations!, you've won!, your score is:" + score);
}
}
}
and this mouseClicked Event
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
public class MyPanel extends JPanel implements MouseListener, ActionListener {
private final Checkers checkers;
private boolean isPanelDisabled;
//MyPanel Constructor that initiates a instance of checkers.
public MyPanel(Checkers checkers) {
this.checkers = checkers;
addMouseListener(this);
}
#Override
public void actionPerformed(ActionEvent e){
}
// Sets the panel colours according to their int number and the boolean condiiton.
#Override
public void mouseClicked(MouseEvent e) {
if (isPanelDisabled == true){
setBackground(Color.CYAN);
}
else{
setBackground(Color.BLACK);
checkers.incrementScore();
}
}
My Expected result of this should be that if the user clicks the 8th panel in that grid, then the color of that panel will be cyan when pressed and not black, but it cant access the boolean variable? where am i going wrong here?
Your question involves communication between objects of different classes, and there are several ways to do this, but most basic is to call a method of an object in one class to the other.
First lets set up the problem,... I've created classes called MyPanel2 and Checkers2, to distinguish them from yours.
Say in MyPanel2 we have a Checkers2 field and a boolean field called selected that is set to false:
private Checkers2 checkers;
private boolean selected = false;
along with appropriate boolean getter and setter:
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return selected;
}
And say within the Checkers2 class you have a 10 instances of MyPanel2 held within an array, and you want the user to be able to "select" instances of the class, but only allow 7 of them to be selected, and assume that you want to user the set up that you're currently using, you could give the main class, a method, public boolean isPanelDisabled(), and have the MyPanel2 class call this method to determine if selection is allowed. So within MyPanel2 you could have a MouseListener with something like:
#Override
public void mousePressed(MouseEvent e) {
if (selected) {
return;
}
// call the Checkers2 boolean method to check
if (checkers.isPanelDisabled()) {
setBackground(DISABLED_COLOR);
} else {
setBackground(SELECTED_COLOR);
setSelected(true);
}
}
Within Checkers2 .isPanelDisabled() method you'd iterate through the array of MyPanel2 instances to see how many have been selected, something like this could work:
public boolean isPanelDisabled() {
int count = 0;
for (MyPanel2 panel2 : myPanels) {
if (panel2.isSelected()) {
count++;
}
}
return count >= MAX_COUNT;
}
The whole MCVE testable code could look like:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Checkers2 extends JFrame {
private static final int MAX_COUNT = 7;
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private MyPanel2[] myPanels = new MyPanel2[NUM];
public Checkers2() {
super("Checkers");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS, 1, 1));
gridPanel.setBackground(Color.BLACK);
gridPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
for (int i = 0; i < myPanels.length; i++) {
MyPanel2 myPanel = new MyPanel2(this);
gridPanel.add(myPanel);
myPanels[i] = myPanel;
}
JButton resetButton = new JButton("Reset");
resetButton.setMnemonic(KeyEvent.VK_R);
resetButton.addActionListener(evt -> {
for (MyPanel2 myPanel2 : myPanels) {
myPanel2.reset();
}
});
JButton exitButton = new JButton("Exit");
exitButton.setMnemonic(KeyEvent.VK_X);
exitButton.addActionListener(evt -> System.exit(0));
JPanel buttonPanel = new JPanel();
buttonPanel.add(resetButton);
add(gridPanel);
add(buttonPanel, BorderLayout.PAGE_END);
pack();
setLocationRelativeTo(null);
}
public boolean isPanelDisabled() {
int count = 0;
for (MyPanel2 panel2 : myPanels) {
if (panel2.isSelected()) {
count++;
}
}
return count >= MAX_COUNT;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Checkers2().setVisible(true);
});
}
}
class MyPanel2 extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private static final int GR = 240;
public static final Color BASE_COLOR = new Color(GR, GR, GR);
public static final Color DISABLED_COLOR = Color.CYAN;
public static final Color SELECTED_COLOR = Color.BLACK;
private Checkers2 checkers;
private boolean selected = false;
public MyPanel2(Checkers2 checkers) {
setBackground(BASE_COLOR);
this.checkers = checkers;
setPreferredSize(new Dimension(PREF_W, PREF_H));
addMouseListener(new MyMouse());
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return selected;
}
public void reset() {
setBackground(BASE_COLOR);
setSelected(false);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if (selected) {
return;
}
if (checkers.isPanelDisabled()) {
setBackground(DISABLED_COLOR);
} else {
setBackground(SELECTED_COLOR);
setSelected(true);
}
}
}
}
Another Option is to take all the logic out of MyPanel and put it into the main program, something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Checkers3 extends JPanel {
private static final int MAX_COUNT = 7;
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private MyPanel3[] myPanels = new MyPanel3[NUM];
public Checkers3() {
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS, 1, 1));
gridPanel.setBackground(Color.BLACK);
gridPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
MyMouse myMouse = new MyMouse();
for (int i = 0; i < myPanels.length; i++) {
MyPanel3 myPanel = new MyPanel3();
myPanel.addMouseListener(myMouse);
gridPanel.add(myPanel);
myPanels[i] = myPanel;
}
JButton resetButton = new JButton("Reset");
resetButton.setMnemonic(KeyEvent.VK_R);
resetButton.addActionListener(evt -> {
for (MyPanel3 myPanel : myPanels) {
myPanel.reset();
}
});
JButton exitButton = new JButton("Exit");
exitButton.setMnemonic(KeyEvent.VK_X);
exitButton.addActionListener(evt -> System.exit(0));
JPanel buttonPanel = new JPanel();
buttonPanel.add(resetButton);
setLayout(new BorderLayout());
add(gridPanel);
add(buttonPanel, BorderLayout.PAGE_END);
}
public boolean isPanelDisabled() {
int count = 0;
for (MyPanel3 panel : myPanels) {
if (panel.isSelected()) {
count++;
}
}
return count >= MAX_COUNT;
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
MyPanel3 myPanel = (MyPanel3) e.getSource();
if (myPanel.isSelected()) {
return; // it's already selected
} else if (isPanelDisabled()) {
myPanel.setSelected(false);
} else {
myPanel.setSelected(true);
}
}
}
private static void createAndShowGui() {
Checkers3 mainPanel = new Checkers3();
JFrame frame = new JFrame("Checkers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class MyPanel3 extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private static final int GR = 240;
public static final Color BASE_COLOR = new Color(GR, GR, GR);
public static final Color DISABLED_COLOR = Color.CYAN;
public static final Color SELECTED_COLOR = Color.BLACK;
private boolean selected = false;
public MyPanel3() {
setBackground(BASE_COLOR);
setPreferredSize(new Dimension(PREF_W, PREF_H));
}
public void setSelected(boolean selected) {
this.selected = selected;
Color background = selected ? SELECTED_COLOR : DISABLED_COLOR;
setBackground(background);
}
public boolean isSelected() {
return selected;
}
public void reset() {
setSelected(false);
setBackground(BASE_COLOR);
}
}
But the BEST option is to put all logic within a separate model class (or classes) and make the GUI's as dumb as possible.
Related
I have 17 JLabel components and I want to add same handler for all these labels. Actually I have have to increase the size of the label when mouse hovers over it. Code is here:
private void lblBackupMouseEntered(java.awt.event.MouseEvent evt) {
lblBackup.setSize(lblBackup.getWidth()+5,lblBackup.getHeight()+5);
}
private void lblChangePasswordMouseEntered(java.awt.event.MouseEvent evt) {
lblChangePassword.setSize(lblChangePassword.getWidth()+5,lblChangePassword.getHeight()+5);
}
private void lblAddEmployeeMouseEntered(java.awt.event.MouseEvent evt) {
lblAddEmployee.setSize(lblAddEmployee.getWidth()+5,lblAddEmployee.getHeight()+5);
}
private void lblAddCustomerMouseEntered(java.awt.event.MouseEvent evt) {
lblAddCustomer.setSize(lblAddCustomer.getWidth()+5,lblAddCustomer.getHeight()+5);
}
Now I want to avoid this repetition of same handler.
It's simple -- you can use the same mouse handler class, and can assign it to multiple JLabels, and then get the current involved JLabel via the MouseEvent#getSource() method.
#Override
public void mouseEntered(MouseEvent evt) {
// assuming that you only add this MouseListener to JLabels...
JLabel currentLabel = (JLabel)evt.getSource();
// do what needs to be done with currentLabel
}
For example:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class ManyLabelExample extends JPanel {
private static final int SIDES = 8;
private static final int GAP = 15;
public static final Color HOVER_COLOR = Color.pink;
private List<JLabel> labels = new ArrayList<>();
public ManyLabelExample() {
setLayout(new GridLayout(SIDES, SIDES));
MyMouseHandler myMouseHandler = new MyMouseHandler();
for (int i = 0; i < SIDES * SIDES; i++) {
String text = String.format("[%d, %d]", i % SIDES + 1, i / SIDES + 1);
JLabel label = new JLabel(text);
label.setOpaque(true);
label.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
label.addMouseListener(myMouseHandler);
labels.add(label);
add(label);
}
}
private class MyMouseHandler extends MouseAdapter {
#Override
public void mouseEntered(MouseEvent evt) {
JLabel source = (JLabel) evt.getSource();
for (JLabel label : labels) {
if (label == source) {
label.setBackground(HOVER_COLOR);
} else {
label.setBackground(null);
}
}
}
}
private static void createAndShowGui() {
ManyLabelExample mainPanel = new ManyLabelExample();
JFrame frame = new JFrame("ManyLabelExample");
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();
}
});
}
}
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();
}
});
}
}
I'm trying to create a program where you press start and a new JFrame comes up with 3 buttons , you have to switch the button after you click on it using a random , I'm fairly new to java so I don't know what to do. Thank you
package code;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;
public class StartListener implements java.awt.event.ActionListener {
private int counter;
private Game Ga;
private JFrame z;
private int x;
public StartListener(Game a, int co){
Ga=a;
counter = co;
}
public void actionPerformed(ActionEvent e) {
Timer time = new Timer(10000,new Time(Ga));
time.start();
z = new JFrame("Sequence game");
FlowLayout fl = new FlowLayout(0, 50, 40);
z.getContentPane().setLayout(fl);
z.setVisible(true);
JButton a = new JButton("A");
Font f = a.getFont();
Font myFont = f.deriveFont(Font.BOLD, f.getSize()*4);
a.setSize(200,100);
a.setVisible(true);
JButton b = new JButton("B");
b.setVisible(true);
b.setSize(200,100);
JButton c = new JButton("C");
c.setVisible(true);
c.setSize(200,100);
z.getContentPane().add(a);
z.getContentPane().add(b);
z.getContentPane().add(c);
z.pack();
Random r = new Random();
x=r.nextInt(3);
figure(a,b,c,x,myFont,f);}
public void figure(JButton a,JButton b, JButton c, int x, Font myFont,Font f){
if(x==0){
a.setEnabled(true);
b.setEnabled(false);
c.setEnabled(false);
a.setFont(myFont);
b.setFont(f);
c.setFont(f);
x =buttonA(a);
figure(a,b,c,x,myFont,f);
;}
else if(x==1){
a.setEnabled(false);
b.setEnabled(true);
c.setEnabled(false);
a.setFont(f);
c.setFont(f);
b.setFont(myFont);
x = buttonB(b);
figure(a,b,c,x,myFont,f);
}
else if(x==2){
a.setEnabled(false);
b.setEnabled(false);
c.setEnabled(true);
a.setFont(f);
b.setFont(f);
c.setFont(myFont);
x = buttonC(c);
figure(a,b,c,x,myFont,f);
}
}
public int buttonA(JButton a){
Random r = new Random();
int rand = 0;
a.addActionListener(new Something(Ga));
rand = r.nextInt(3);
return rand;
}
public int buttonB(JButton b){
Random r = new Random();
int rand = 0;
b.addActionListener(new Something(Ga));
rand=r.nextInt(3);
return rand;
}
public int buttonC(JButton c){
Random r = new Random();
int rand=0;
c.addActionListener(new Something(Ga));
rand = r.nextInt(3);
return rand;
}
}
And here's the code for Something
package code;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Something implements ActionListener {
private Game G;
public Something(Game a){
G = a;
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
G.increment();
}
}
Here's the error :
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.awt.Component.enable(Unknown Source)
at java.awt.Component.setEnabled(Unknown Source)
at javax.swing.JComponent.setEnabled(Unknown Source)
at javax.swing.AbstractButton.setEnabled(Unknown Source)
Your figure method continuously calls itself recursively forever, or until stack space runs out. Solution: get rid of those recursive calls. Also you really don't want to keep adding multiple ActionListeners on to JButtons, all this suggesting that you will want to refactor and perhaps redesign the entire program.
You will want to change the state of a field in the class, and use that field's state to decide what to do within the ActionListener.
For example:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class SwapButtons extends JPanel {
private static final Font ACTIVE_FONT = new Font(Font.DIALOG, Font.BOLD, 15);
private static final String[] BTN_TEXT = { "Monday", "Tuesday", "Wednesday" };
private static final int EXTRA_WIDTH = 50;
private List<AbstractButton> buttonList = new ArrayList<>();
private int buttonIndex = 0;
public SwapButtons() {
setLayout(new GridLayout(1, 0, 5, 0));
BtnListener btnListener = new BtnListener();
for (int i = 0; i < BTN_TEXT.length; i++) {
JButton button = new JButton(BTN_TEXT[i]);
button.addActionListener(btnListener);
buttonList.add(button); // add to ArrayList
add(button); // add to GUI
}
setActiveButton();
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
// give preferred size extra width so gui can handle larger fonts
int prefW = superSz.width + EXTRA_WIDTH;
int prefH = superSz.height;
return new Dimension(prefW, prefH);
}
private void setActiveButton() {
// iterate through buttonList, turning on the "active" button
// as determined by the buttonIndex variable
for (int i = 0; i < buttonList.size(); i++) {
if (i == buttonIndex) {
buttonList.get(i).setFont(ACTIVE_FONT);
buttonList.get(i).setEnabled(true);
} else {
buttonList.get(i).setFont(null);
buttonList.get(i).setEnabled(false);
}
}
}
private class BtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// show which button pressed
System.out.println("Button Pressed: " + e.getActionCommand());
// advance button index so that next button can be activated
buttonIndex++;
// but change index to 0 if buttonList size is reached
buttonIndex %= buttonList.size();
// activate the next button:
setActiveButton();
}
}
private static void createAndShowGui() {
SwapButtons mainPanel = new SwapButtons();
JFrame frame = new JFrame("Swap Buttons");
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();
}
});
}
}
I have been trying to get my code to reset after hitting the okay button with slider, however, I have had no such luck. Does anyone have an idea on how I can incorporate this into my code?
P.S. The reset must be in Class Field.
package GUI;
import java.awt.GridLayout;
import javax.swing.JPanel;
public class GameDisplay extends JPanel {
private static final long serialVersionUID = 1L;
private boolean activated;
public GameDisplay(Model.Field field) {
setLayout(new GridLayout(GUI.SizeDialog.currentRows, GUI.SizeDialog.currentColumns));
for (int i = 0; i < GUI.SizeDialog.currentRows; ++i) {
for (int j = 0; j < GUI.SizeDialog.currentColumns; ++j) {
add(field.Cells[i][j]);
}
}
}
public boolean isActive() {
return activated;
}
public void setActive(boolean activated) {
this.activated = activated;
}
}
Field
package Model;
import java.awt.Dimension;
import java.util.ArrayList;
import GUI.SizeDialog;
public class Field {
private int difficultyFactor;
public static final int EASY = 1;
public static final int NORMAL = 2;
public static final int HARD = 3;
public Cell[][] Cells;
public Field() {
Cells = new Cell[GUI.SizeDialog.currentRows][GUI.SizeDialog.currentColumns];
for (int i = 0; i < GUI.SizeDialog.currentRows; ++i) {
for (int j = 0; j < GUI.SizeDialog.currentColumns; ++j) {
Cells[i][j]= new Cell();
}
}
}
public void reset(){
Cells = new Cell[GUI.SizeDialog.currentRows][GUI.SizeDialog.currentColumns];
for (int i = 0; i < GUI.SizeDialog.currentRows; ++i) {
for (int j = 0; j < GUI.SizeDialog.currentColumns; ++j) {
Cells[i][j]= new Cell();
}
}
}
public void setDifficultyFactor(int level) {
switch (level) {
case EASY:
difficultyFactor = EASY;
break;
case NORMAL:
difficultyFactor = NORMAL;
break;
case HARD:
difficultyFactor = HARD;
break;
default:
difficultyFactor = NORMAL;
}
}
}
SizeDialog
package GUI;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import Model.Field;
public class SizeDialog extends JDialog {
private static final long serialVersionUID = 1L;
private Model.Field field;
private GUI.GameDisplay GameDisplay;
public static Integer currentRows = 4;
public static Integer currentColumns = 4;
public SizeDialog() {
JPanel dialogBoxPanel = new JPanel();
BorderLayout dialogLayout = new BorderLayout();
dialogBoxPanel.setLayout(dialogLayout);
JSlider rowCount = new JSlider(4, 10, 4);
JSlider columnCount = new JSlider(4, 10, 4);
Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
labelTable.put(new Integer(4), new JLabel("4"));
labelTable.put(new Integer(10), new JLabel("10"));
rowCount.setLabelTable(labelTable);
rowCount.setPaintLabels(true);
columnCount.setLabelTable(labelTable);
columnCount.setPaintLabels(true);
JLabel row = new JLabel();
JLabel column = new JLabel();
JPanel rowPanel = new JPanel();
JPanel columnPanel = new JPanel();
JLabel rowPosition = new JLabel();
rowPosition.setText("Rows: 4");
JLabel columnPosition = new JLabel();
columnPosition.setText("Columns: 4");
rowCount.addChangeListener(getCurrentRows(rowCount, "row", rowPosition));
columnCount.addChangeListener(getCurrentColumns(columnCount, "column", columnPosition));
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
field.reset();
SizeDialog.this.dispose();
}
});
rowPanel.add(rowPosition, BorderLayout.WEST);
rowPanel.add(row, BorderLayout.CENTER);
rowPanel.add(rowCount, BorderLayout.EAST);
columnPanel.add(columnPosition, BorderLayout.WEST);
columnPanel.add(column, BorderLayout.CENTER);
columnPanel.add(columnCount, BorderLayout.EAST);
dialogBoxPanel.add(rowPanel, BorderLayout.NORTH);
dialogBoxPanel.add(columnPanel, BorderLayout.CENTER);
dialogBoxPanel.add(okButton, BorderLayout.SOUTH);
setContentPane(dialogBoxPanel);
setMinimumSize(new Dimension(300, 150));
setLocationRelativeTo(null);
}
private ChangeListener getCurrentColumns(final JSlider columnCount, final String string, final JLabel columnPosition) {
ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
JSlider theSlider = (JSlider) changeEvent.getSource();
if (!theSlider.getValueIsAdjusting()) {
int sliderValue = theSlider.getValue();
columnPosition.setText("columns:" + sliderValue);
SizeDialog.currentColumns = sliderValue;
}
}
};
return changeListener;
}
private ChangeListener getCurrentRows(final JSlider rowCount, final String string, final JLabel rowPosition) {
ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
JSlider theSlider = (JSlider) changeEvent.getSource();
if (!theSlider.getValueIsAdjusting()) {
int sliderValue = theSlider.getValue();
rowPosition.setText("Rows:" + sliderValue);
SizeDialog.currentRows = sliderValue;
}
}
};
return changeListener;
}
}
MainFrame
package GUI;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static JPanel centerPanel;
public static final String EASY = "Easy";
public static final String NORMAL = "Normal";
public static final String HARD = "Hard";
public MainFrame(JPanel centerPanel) {
// Setup of Main
super("The True/False Game");
this.centerPanel = centerPanel;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setup();
}
private void setup() {
// Setup of centerPanel
add(centerPanel);
pack();
}
public JMenuBar setUpMenuBar(ActionListener listener) {
// create the necessary menu items and menus
JMenuBar menuBar = new JMenuBar();
JMenu settingsMenu = new JMenu("Settings");
JMenuItem size = new JMenuItem("Size");
size.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object valueBox = new SizeDialog();
((Window) valueBox).setVisible(true);
}
});
JMenu difficultyMenu = new JMenu("Difficulty Level");
ButtonGroup levelGroup = new ButtonGroup();
JCheckBoxMenuItem easyDifficultyItem = new JCheckBoxMenuItem(EASY);
JCheckBoxMenuItem normalDifficultyItem = new JCheckBoxMenuItem(NORMAL);
JCheckBoxMenuItem hardDifficultyItem = new JCheckBoxMenuItem(HARD);
easyDifficultyItem.setSelected(true); // Default difficulty setting
// this button group ensures that only one check box is selected
levelGroup.add(easyDifficultyItem);
levelGroup.add(normalDifficultyItem);
levelGroup.add(hardDifficultyItem);
difficultyMenu.add(easyDifficultyItem);
difficultyMenu.add(normalDifficultyItem);
difficultyMenu.add(hardDifficultyItem);
settingsMenu.add(size);
settingsMenu.add(difficultyMenu);
menuBar.add(settingsMenu);
// use a single listener to handle all menu item selections
for (int i = 0; i < menuBar.getMenuCount(); ++i) {
for (JMenuItem item : getMenuItems(menuBar.getMenu(i))) {
item.addActionListener(listener);
}
}
return menuBar;
}
// this recursion works because JMenu is a subclass of JMenuItem!
private static List<JMenuItem> getMenuItems(JMenuItem item) {
List<JMenuItem> items = new ArrayList<>();
if (item instanceof JMenu) {
JMenu menu = (JMenu) item;
for (int i = 0; i < menu.getItemCount(); ++i) {
items.addAll(getMenuItems(menu.getItem(i)));
}
} else {
items.add(item);
}
return items;
}
}
App
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenuBar;
import Model.Cell;
import Model.Field;
import GUI.MainFrame;
import GUI.SizeDialog;
public class App {
// Main Objects
private static GUI.MainFrame MainFrame;
private static GUI.GameDisplay GameDisplay;
private static Model.Field field;
public static GUI.SizeDialog SizeDialog;
public static void main(String[] args) {
// Setup of the Main Objects
field = new Model.Field();
GameDisplay = new GUI.GameDisplay(field);
MainFrame = new MainFrame(GameDisplay);
MainFrame.setMinimumSize(new Dimension(500, 500));
MainFrame.getContentPane().add(GameDisplay);
// Setup of the Menu Bar
JMenuBar menuBar = MainFrame.setUpMenuBar(menuListener);
MainFrame.setJMenuBar(menuBar);
// Show the Mainframe in the center of the desktop screen
MainFrame.setLocationRelativeTo(null);
MainFrame.setVisible(true);
}
// listener for the menu items in MainFrame
private static ActionListener menuListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case GUI.MainFrame.EASY:
field.setDifficultyFactor(Field.EASY);
GameDisplay.setActive(true);
break;
case GUI.MainFrame.NORMAL:
field.setDifficultyFactor(Field.NORMAL);
GameDisplay.setActive(true);
break;
case GUI.MainFrame.HARD:
field.setDifficultyFactor(Field.HARD);
GameDisplay.setActive(true);
break;
}
}
};
};
An instance of your Field class is currently being created in the App class. Your private field field in the SizeDialog class is currently not being set to the instance known to the App class. A solution for this problem is to provide the Field instance as a parameter.
A possible solution is as follows:
App:
public class App {
// Main Objects
private static GUI.MainFrame MainFrame;
private static GUI.GameDisplay GameDisplay;
private static Model.Field field;
public static GUI.SizeDialog SizeDialog;
public static void main(String[] args) {
// Setup of the Main Objects
field = new Model.Field();
GameDisplay = new GUI.GameDisplay(field);
MainFrame = new MainFrame(GameDisplay, field);
/* the rest of your code */
}
/* more App code */
}
MainFrame:
public class MainFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static JPanel centerPanel;
public static final String EASY = "Easy";
public static final String NORMAL = "Normal";
public static final String HARD = "Hard";
private Model.Field field;
public MainFrame(JPanel centerPanel, Model.Field field) {
this.field = field;
/* the rest of your code */
}
public JMenuBar setUpMenuBar(ActionListener listener) {
// create the necessary menu items and menus
JMenuBar menuBar = new JMenuBar();
JMenu settingsMenu = new JMenu("Settings");
JMenuItem size = new JMenuItem("Size");
size.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object valueBox = new SizeDialog(field);
((Window) valueBox).setVisible(true);
}
});
/* the rest of your code */
}
/* more MainFrame code */
}
SizeDialog:
public class SizeDialog extends JDialog {
private static final long serialVersionUID = 1L;
private final Model.Field field;
private GUI.GameDisplay GameDisplay;
public static Integer currentRows = 4;
public static Integer currentColumns = 4;
public SizeDialog(final Model.Field field) {
this.field = field;
/* the rest of your code */
}
/* more SizeDialog code */
}
EDIT: As mentioned in this answer, objects that are referenced in anonymous classes must be final.
Simple question for you , i input this code and i see the combobox and the label, but after the selection of the combo the label should be with an image. This does not happen ... Surely i forgot something
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChooseFrame extends JFrame
{
public ChooseFrame()
{
labelLeagueImage = new JLabel("Liga");
comboLeague = createComboLeague();
class ChooseListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
String league = (String)comboLeague.getSelectedItem();
if (league.equals("Italia - Serie A"))
{
ImageIcon icon = new ImageIcon("Italia - Serie A.png");
labelLeagueImage.setIcon(icon);
}
}
}
listener = new ChooseListener();
leaguePanel = new JPanel();
leaguePanel.add(comboLeague);
leaguePanel.add(labelLeagueImage);
add(leaguePanel);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public JComboBox createComboLeague()
{
JComboBox combo = new JComboBox();
combo.addItem("Select a league");
combo.addItem("Italia - Serie A");
combo.addItem("Italia - Serie B");
combo.addActionListener(listener);
return combo;
}
private JPanel leaguePanel;
private JComboBox comboLeague;
private JLabel labelLeagueImage;
private ActionListener listener;
private static final int FRAME_WIDTH = 300;
private static final int FRAME_HEIGHT = 600;
}
At the time you create the combo box and assign the listener, in createComboLeague(), the listener is still null. It's initialized only after the createComboLeague() method has been called.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChooseFrame extends JFrame
{
private JPanel leaguePanel;
private JComboBox comboLeague;
private JLabel labelLeagueImage;
private ActionListener listener;
private static final int FRAME_WIDTH = 300;
private static final int FRAME_HEIGHT = 600;
public ChooseFrame()
{
labelLeagueImage = new JLabel("Liga");
comboLeague = createComboLeague();
// listener = new ChooseListener();
leaguePanel = new JPanel();
leaguePanel.add(comboLeague);
leaguePanel.add(labelLeagueImage);
add(leaguePanel);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public JComboBox createComboLeague()
{
JComboBox combo = new JComboBox();
combo.addItem("Select a league");
combo.addItem("Italia - Serie A");
combo.addItem("Italia - Serie B");
combo.addActionListener(listener);
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
// TODO Auto-generated method stub
String league = (String)comboLeague.getSelectedItem();
if (league.equals("Italia - Serie A"))
{
ImageIcon icon = new ImageIcon("Italia - Serie A.png");
labelLeagueImage.setIcon(icon);
}
}
});
return combo;
}
public static void main(String[] args) {
ChooseFrame cs=new ChooseFrame();
cs.setVisible(true);
}
}