I'm working on a TicTacToe game at the moment as a personal project and so far I know I'm almost complete with the game except for the part where I have to check if the x or o's are equal and in a line. Here's my code below here. My problem is in the connected method, it compiles and run's, but when I tried to add the middle horizontal row after just only one JButton was pressed it said the person won which should not be the case. I think I need a method that is named isDisabled(), instead of isEnabled for the JButton, but for some reason I don't think there is such a method in the java library. I know for sure if I had isDisabled() it would work for sure
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created by Usman on 5/17/2016.
*/
public class TicTacToeGUI extends JPanel {
boolean turn = true;
JButton[] board;
public TicTacToeGUI() {
setLayout(new GridLayout(3,3));
board = new JButton[9];
for (int i = 0; i < board.length; i++) {
board[i] = new JButton("");
board[i].setPreferredSize(new Dimension(70, 60));
board[i].setFont(new Font("Arial", Font.PLAIN, 40));
int finalI = i;
board[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(board[finalI].isEnabled()){
if(turn){
board[finalI].setText("X");
turn = !turn;
}
else{
board[finalI].setText("O");
turn = true;
}
board[finalI].setEnabled(false);
}
Connected();
}
});
add(board[i]);
}
}
public void Connected(){
int count =0;
//Horizontal top row
if((board[0].isEnabled() == board[1].isEnabled()) && (board[1].isEnabled() == board[2].isEnabled())){
System.out.println(count++);
for(int i = 0; i < board.length; i++)
board[i].setEnabled(false);
}
}
public static void main(String []args){
TicTacToeGUI game = new TicTacToeGUI();
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(game);
frame.pack();
frame.setVisible(true);
}
}
Just use (!whatever.isEnabled())
The character '!' is similar to a NOT in Java. So it will behave like isDiabled()
Related
I'm trying to write a checkers AI program with a GUI in java. I've managed to initialise and fill the board so far (with pieces written as "B" and "W" for now). I've created a 2D JButton panel for the board.
I don't know how to proceed when moving pieces. My current issue is I need the player to select a preexisting piece (action 1) and then an empty space to place the selected piece (action 2). Of course these actions are dependent, and I need action 1 to happen first.
Here's what I've got so far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class Checkers implements ActionListener{
private static final int BOARD_SIZE = 8;
Random random = new Random();
JFrame frame = new JFrame();
JPanel title_panel = new JPanel();
JPanel button_panel = new JPanel();
JLabel textfield = new JLabel();
JButton[][] buttons = new JButton[BOARD_SIZE][BOARD_SIZE];
Checkers(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,800);
frame.getContentPane().setBackground(new Color(50, 50, 50));
frame.setLayout(new BorderLayout());
frame.setVisible(true);
textfield.setBackground(new Color(25,25,25));
textfield.setForeground(new Color(25, 255, 0));
textfield.setFont(new Font("Arial", Font.BOLD, 75));
textfield.setHorizontalAlignment(JLabel.CENTER);
textfield.setText("Checkers");
textfield.setOpaque(true);
title_panel.setLayout(new BorderLayout());
title_panel.setBounds(0,0,800, 100);
button_panel.setLayout(new GridLayout(BOARD_SIZE,BOARD_SIZE));
button_panel.setBackground(new Color(150,150,150));
for (int i=0; i<BOARD_SIZE; i++){
for (int j=0; j<BOARD_SIZE; j++){
buttons[i][j] = new JButton();
button_panel.add(buttons[i][j]);
buttons[i][j].setFont(new Font("Arial",Font.BOLD, 30));
buttons[i][j].setFocusable(false);
buttons[i][j].addActionListener(this);
}
}
title_panel.add(textfield);
frame.add(title_panel, BorderLayout.NORTH);
frame.add(button_panel);
initialiseBoard(buttons);
}
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
if (e.getSource() == buttons[i][j]) {
String moving_piece = buttons[i][j].getText();
}
}
}
}
// method that fills the initial board.
public void initialiseBoard(JButton[][] buttons){
for (int i=0; i<BOARD_SIZE; i++){
for (int j=0; j<BOARD_SIZE; j++){
if (i<3){
if (i%2==0){
if (j%2 != 0){
buttons[i][j].setText("W");
}
}
else {
if (j%2==0){
buttons[i][j].setText("W");
}
}
}
if (i>=BOARD_SIZE-3){
if (i%2 == 0){
if (j%2 != 0){
buttons[i][j].setText("B");
}
}
else {
if (j%2==0){
buttons[i][j].setText("B");
}
}
}
}
}
}
}
As I mentioned in my comment, the key to a solution is to base your program's listener on "state-dependent behavior", meaning the behavior of the listener will depend on the state of the program.
For instance, if you give your program an instance field, say, selectedButton that held a reference to the last selected button, then any ActionListener's response can vary depending on what this field holds. The first time any JButton is pressed, this field will hold null since no previous JButton was pressed, and so the ActionListener will assign this button to that field. The second time that the ActionListener is called (the second time that a JButton is pressed), the field will hold a value, and so, using an if / else block that checks the state of this field, the listener's behavior can vary:
public class Checkers2 {
private static final int BOARD_SIZE = 8;
// .....
private JButton[][] buttons = new JButton[BOARD_SIZE][BOARD_SIZE];
private JButton selectedButton = null;
public Checkers2() {
buttonPanel.setLayout(new GridLayout(BOARD_SIZE, BOARD_SIZE));
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons[i].length; j++) {
buttons[i][j] = new JButton(" ");
buttonPanel.add(buttons[i][j]);
buttons[i][j].setFont(BTN_FONT);
buttons[i][j].setPreferredSize(BTN_SIZE);
buttons[i][j].addActionListener(e -> btnsActionPerormed(e));
}
}
// ...
}
private void btnsActionPerormed(ActionEvent e) {
JButton source = (JButton) e.getSource();
// if selectedButton is null, then this is the first press
if (selectedButton == null) {
if (source.getText().trim().isEmpty()) {
return; // no button text means that there is no piece here. Exit method
} else {
// first set the selectedButton's value
selectedButton = source;
// change its appearance so we know that it has been pressed
source.setForeground(Color.RED);
source.setBackground(Color.LIGHT_GRAY);
}
} else {
// else, if selectedButton is NOT null, then this is the second press
// only do things if this current button is empty, if it has no text
if (source.getText().trim().isEmpty()) {
selectedButton.setForeground(Color.BLACK);
selectedButton.setBackground(null);
source.setText(selectedButton.getText());
selectedButton.setText("");
// the code below is of key importance
selectedButton = null;
}
}
}
The last bit of code shown is also key -- with the second JButton press, we re-set selectedButton back to null, so that the program's state is set back to its initial state and so that the listener's initial behavior can repeat.
A simple example program that demonstrates this is as shown below. The program still has not encorporated true Checker's game logic where the program determines if a move is truly legal or not:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class Checkers2 {
private static final int BOARD_SIZE = 8;
private static final Font BTN_FONT = new Font("Arial", Font.BOLD, 30);
private static final Dimension BTN_SIZE = new Dimension(100, 100);
private JPanel buttonPanel = new JPanel();
private JButton[][] buttons = new JButton[BOARD_SIZE][BOARD_SIZE];
private JButton selectedButton = null;
public Checkers2() {
buttonPanel.setLayout(new GridLayout(BOARD_SIZE, BOARD_SIZE));
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons[i].length; j++) {
buttons[i][j] = new JButton(" ");
buttonPanel.add(buttons[i][j]);
buttons[i][j].setFont(BTN_FONT);
buttons[i][j].setPreferredSize(BTN_SIZE);
buttons[i][j].addActionListener(e -> btnsActionPerormed(e));
}
}
// Place "W" and "B" text in appropriate locations:
for (int i = 0; i < 12; i++) {
int wI = (2 * i) / BOARD_SIZE;
int wJ = (2 * i) % BOARD_SIZE + ((wI % 2 == 1) ? 0 : 1);
buttons[wI][wJ].setText("W");
buttons[BOARD_SIZE - wI - 1][BOARD_SIZE - wJ - 1].setText("B");
}
}
private void btnsActionPerormed(ActionEvent e) {
JButton source = (JButton) e.getSource();
// if selectedButton is null, then this is the first press
if (selectedButton == null) {
if (source.getText().trim().isEmpty()) {
return; // no button text means that there is no piece here. Exit method
} else {
// first set the selectedButton's value
selectedButton = source;
// change its appearance so we know that it has been pressed
source.setForeground(Color.RED);
source.setBackground(Color.LIGHT_GRAY);
}
} else {
// else, if selectedButton is NOT null, then this is the second press
// only do things if this current button is empty, if it has no text
if (source.getText().trim().isEmpty()) {
selectedButton.setForeground(Color.BLACK);
selectedButton.setBackground(null);
source.setText(selectedButton.getText());
selectedButton.setText("");
// the code below is of key importance
selectedButton = null;
}
}
}
public JPanel getButtonPanel() {
return buttonPanel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Checkers2 checkers = new Checkers2();
JFrame frame = new JFrame("Checkers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(checkers.getButtonPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
And I hope to show how to encorporate program logic in an edit. For this, I recommend using a "Model-View-Controller" or MVC program structure.
You need to memorize and manage the selection of a piece. You can do it by:
//Introduce a field to store selected button
private JButton selected = null ;
And modify the ActionListener:
#Override
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
if(selected != null ){
clicked.setText(selected.getText());
selected.setText("");
selected = null;
}else{
if( ! clicked.getText().isEmpty()) {
selected = clicked;
}
}
}
Consider using JToggleButtons instead of a JButtons .
I need to finish up this simon game for my beginner Java class. Basically the game needs to randomize 3 of the COLOR letters on the top label "R", "B", "Y" or "G" to begin playing the game. The player will press the colors in this sequence and if they are correct it will add another letter/color if they are wrong they will lose. I have the main part of the game set up including color ect... What I am having a hard time with is printing the letters of the buttons pushed on the bottom label and also getting the top label to randomize 3 to start with. I can get the game to print random letters on the top label when a button is pushed but it wont do this own its own to start and it wont add the letters on?
HERE IS MY CODE:
//10/30/16
package simongame1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.security.SecureRandom;
public class SimonGame1 extends JFrame implements ActionListener
{
public SecureRandom rand;
public String randomLetters="";
JButton[] numberButtons = new JButton[4];
JPanel numberButtonPanel = new JPanel();
JLabel labelTop;
JLabel labelBottom;
String messageTop = "";
String messageBottom = "";
JButton red;
JButton green;
JButton yellow;
JButton blue;
public final String letters= "RGBY";
public JLabel labelDisplay;
//constructor?
public SimonGame1()
{
super("Simon Game!");
labelDisplay = new JLabel ("");
setLayout(new BorderLayout());
red = new JButton();
green = new JButton();
blue = new JButton();
yellow = new JButton();
labelTop = new JLabel("");
//getRandomLetter();
labelBottom = new JLabel("");
//System.out.print (randomLetters);
rand = new SecureRandom();
numberButtons = new JButton[4];
numberButtonPanel = new JPanel();
numberButtonPanel.setLayout(new GridLayout(3,3));
for(int i = 0; i < 0; i++)
{
numberButtons[i] = new JButton();
numberButtonPanel.add(numberButtons[i]);
numberButtons[i].addActionListener(this);
}
numberButtonPanel.add(red);
red.setBackground(Color.red);
red.addActionListener(this);
numberButtonPanel.add(blue);
blue.setBackground(Color.blue);
blue.addActionListener(this);
numberButtonPanel.add(yellow);
yellow.setBackground (Color.yellow);
yellow.addActionListener(this);
numberButtonPanel.add (green);
green.setBackground (Color.green);
green.addActionListener(this);
add(labelTop, BorderLayout.NORTH);
add(labelBottom, BorderLayout.SOUTH);
add(numberButtonPanel, BorderLayout.CENTER);
//if (messageTop = messageBottom)
}
// TODO code application logic here
#Override
public void actionPerformed(ActionEvent e)
{
rand = new SecureRandom();
randomLetters+= getRandomLetter();
labelTop.setText (randomLetters);
labelBottom.setText (letters);
System.out.println(e.getID());
if(e.getSource() == red)
{
System.out.println("R");
}
else if (e.getSource()==blue)
{
System.out.println ("B");
}
else if (e.getSource()==yellow)
{
System.out.println ("Y");
}
else if (e.getSource()==green)
{
System.out.println ("G");
}
}
public char getRandomLetter()
{
char randChar = letters.charAt(rand.nextInt (4));
return randChar;
}
}
AND HERE IS THE TEST
package simongame1;
import javax.swing.JFrame;
public class NewClass {
public static void main(String[] args) {
{
SimonGame1 simpleFrame = new SimonGame1();
simpleFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
simpleFrame.setSize(300, 300);
simpleFrame.setVisible(true);
}
}
}
WHY IS THIS ONE CLICK BEHIND? If i click the red button it doenst show anything but if i click the blue one after the red thats when it prints "R" finally...
labelBottom.setText (messageBottom);
**//WHY IS IT ONE LETTER BEHIND?**
System.out.println(e.getID());
if(e.getSource() == red)
{
messageBottom += "R";
//System.out.println("R");
}
else if (e.getSource()==blue)
{
messageBottom += "B";
//System.out.println ("B");
}
else if (e.getSource()==yellow)
{
messageBottom += "Y";
//System.out.println ("Y");
}
else if (e.getSource()==green)
{
messageBottom += "G";
//System.out.println ("G");
}
When you initialize your label, before you add it to the panel I would just generate the label with the letters you need and set the text of the label right there. That way when you add it you will for sure have the characters in there. Right now you are only setting the text of labelTop when the actionPerformed method is called, which is only called when a button is pressed.
So it should look something like:
public SimonGame1() {
//....
rand = new SecureRandom();
labelTop = new JLabel( "" );
//initialize with 3
for(int i = 0; i < 3; i++)
{
randomLetters += getRandomLetter();
}
labelTop.setText( randomLetters );
//...
add(labelTop, BorderLayout.NORTH);
}
also this block of code is not used at all because the condition is never met, since you initialize i to 0 and then say as long as it is less than 0:
for(int i = 0; i < 0; i++)
{
numberButtons[i] = new JButton();
numberButtonPanel.add(numberButtons[i]);
numberButtons[i].addActionListener(this);
}
EDIT:
since you added another part of the question, you asked why it is waiting an iteration before adding the character you just clicked in your actionPerformed method, and that is because you are setting the text before you add the next character to the string. So your actionPerformed method should look like:
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == red)
{
messageBottom += "R";
//System.out.println("R");
}
else if (e.getSource()==blue)
{
messageBottom += "B";
//System.out.println ("B");
}
else if (e.getSource()==yellow)
{
messageBottom += "Y";
//System.out.println ("Y");
}
else if (e.getSource()==green)
{
messageBottom += "G";
//System.out.println ("G");
}
labelBottom.setText (messageBottom);
}
I am gonna re-post this questione again trying to be more precise and hoping I will get some help because this is driving me crazy. I am developing a board game with up to 6 player, each one with a different colored pawn. I have the following image that is loaded in BufferedImage arrays treating it as a sprite:
and this is the relative code, putting each face of each colored die in a position in the BufferedImage[]:
private BufferedImage[] initAnimationBuffer() {
BufferedImage[] result = new BufferedImage[36];
for (int i = 0; i < 6; i++) {
for (int j = i; j < 6 + i; j++)
result[i + j] = DieSprite.getSprite(j, i, 0);
}
return result;
}
Then each player, according to his color, wil have also the following matrix containing the faces of his color according to the obtained die value/position. In other words this matrix contains "a line" of the image and it is indexed by value:
private BufferedImage[][] initExactDieFaces() {
BufferedImage[][] result = new BufferedImage[6][1];
int row = -1;
String myColor = this.coreGame.getMyPartecipant().getColor();
if (myColor.equals(Constants.COLOR[0])) {
row = 0;
} else if (myColor.equals(Constants.COLOR[1])) {
row = 2;
} else if (myColor.equals(Constants.COLOR[2])) {
row = 4;
} else if (myColor.equals(Constants.COLOR[3])) {
row = 1;
} else if (myColor.equals(Constants.COLOR[4])) {
row = 5;
} else if (myColor.equals(Constants.COLOR[5])) {
row = 3;
}
int offset = 0;
for (int i = 0; i < 6; i++) {
result[i][0] = DieSprite.getSprite(row, i, offset);
offset += 2;
}
return result;
}
What I want is the following:
-when the "flip die" button is pressed, I want that (for example) 20 random die faces are shown (they should be taken from the first array, AnimationBuffer) in a specific JLabel inside a JPanel
-as soon as the previous animation has finished, I want that the obtained result of the launch of the die is shown (according to the color pawn, taken from ExcatDieFaces).
To get this I know that I need Swing Timer but I am not able to put it all together; here's some code of the startAnimationDie method which is called when the "flip die" button is pressed:
private void startAnimationDie(final JPanel dieContainer) {
final BufferedImage[] animationBuffer = initAnimationBuffer();
final BufferedImage[][] exactDieFaces = initExactDieFaces();
final AnimationSprite animation = new AnimationSprite(
animationBuffer, Constants.DIE_ANIMATION_SPEED);
/* getting launch value fromt the core Game */
int launchResult = coreGame.launchDie();
coreGame.getMyPartecipant().setLastLaunch(launchResult);
final Timer timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dieContainer.removeAll();
dieContainer.updateUI();
animation.start();
JLabel resultDie = new JLabel();
resultDie.setBounds(60, 265, Constants.DIE_SIZE,Constants.DIE_SIZE);
resultDie.setIcon(new ImageIcon(animationBuffer[new Random().nextInt(36)]));
dieContainer.add(resultDie);
dieContainer.updateUI();
updateUI();
repaint();
}
});
/* animation begins, rolling faces are shown each time the Timer ends*/
for(int i = 0; i<20; i++)
timer.start()
/* showing the final face according to the pawn color and the obtained result from the launch */
dieContainer.removeAll();
dieContainer.updateUI();
AnimationSprite resultAnimation = new AnimationSprite(exactDieFaces[launchResult - 1], 6);
resultAnimation.start();
resultAnimation.update();
resultDie.setIcon(new ImageIcon(exactDieFaces[launchResult - 1][0]));
resultDie.setBounds(60, 265, Constants.DIE_SIZE, Constants.DIE_SIZE);
dieContainer.add(resultDie);
dieContainer.updateUI();
dieContainer.repaint();
}
How can I make it work? I think I am supposed to use Swing.invokeAndWait but I cannot put together all the pieces...Can you help please?
Don't call updateUI, unless you're dealing with installing a look and feel, it's not doing what you think it is (and it's very inefficient)
Don't rebuild the UI each time, this is time consuming work, which is going to make the animation look stilled and staggered and probably flash a lot. Instead, simply update the icon property of the label
Use a single Timer, allow it to increment a counter, so you know how many times it's been called and update the die roll and counter on each tick.
Think of the Timer as a kind of loop, where on each iteration (tick), you need to do something (like increment the counter)
(Note- When it looks like the die has "stalled", it's because the image is been displayed more then once in sequence. You could over come this by placing all the images into a List and using Collections.shuffle. Do this three times, adding the result to another List should give you 24, no-repeating sequence (ok, it "might" repeat on the boundaries, but it's better then using Math.random ;))
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage[] dice = new BufferedImage[6];
private JLabel die;
public TestPane() {
try {
BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Documents/Die.png"));
int width = 377 / 6;
for (int index = 0; index < 6; index++) {
dice[index] = img.getSubimage(width * index, 0, width, width);
}
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
die = new JLabel(new ImageIcon(dice[0]));
add(die, gbc);
JButton roll = new JButton("Roll");
add(roll, gbc);
roll.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
roll.setEnabled(false);
Timer timer = new Timer(250, new ActionListener() {
private int counter;
private int lastRoll;
#Override
public void actionPerformed(ActionEvent e) {
if (counter < 20) {
counter++;
lastRoll = (int)(Math.random() * 6);
System.out.println(counter + "/" + lastRoll);
die.setIcon(new ImageIcon(dice[lastRoll]));
} else {
lastDieRollWas(lastRoll);
((Timer)e.getSource()).stop();
roll.setEnabled(true);
}
}
});
timer.start();
}
});
}
protected void lastDieRollWas(int roll) {
System.out.println("You rolled " + (roll + 1));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
I have an int a; in the main class and i'd like to use it in the Action Listner class. I've checked for answers but didnt really understand what i had to do since I'm still just a begginer in any kind of programing so if its possible i'd really appreciate a simple solution.
here is my code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Start {
public static void main(String[] args){
JFrame okno = new JFrame("Nonogram");
okno.setVisible(true);
okno.setSize(700, 700);
okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
okno.add(panel);
JButton [][] gumbi = new JButton[15][15];
JPanel polje = new JPanel(new GridLayout(15, 15));
panel.add(polje, BorderLayout.CENTER);
int a = 1;
int b = 1;
for(int i = 0; 0 < 15; i++){
for(int j = 0; j < 15; j++){
if(i < 5 && j < 5){
gumbi[i][j] = new JButton();
gumbi[i][j].setBackground(Color.RED);
//gumbi[i][j].addActionListener(new Listener(gumbi));
polje.add(gumbi[i][j]);
}else if(i < 5 || j < 5){
gumbi[i][j] = new JButton();
gumbi[i][j].setBackground(Color.YELLOW);
//gumbi[i][j].addActionListener(new Listener(gumbi));
polje.add(gumbi[i][j]);
gumbi[i][j].setEnabled(false);
}else{
if(Math.random() <= 0.6){
gumbi[i][j] = new JButton();
gumbi[i][j].setBackground(Color.WHITE);
gumbi[i][j].addActionListener(new Listener(gumbi));
gumbi[i][j].setText("3");
polje.add(gumbi[i][j]);
}else {
gumbi[i][j] = new JButton();
gumbi[i][j].setBackground(Color.WHITE);
gumbi[i][j].addActionListener(new Listener(gumbi));
gumbi[i][j].setText("4");
polje.add(gumbi[i][j]);
}
}
if(gumbi[i][j].getText() == "3"){
a += 1;
}
if(i == 14 && j == 14){
gumbi[i][j].setText("" + a);
}
}
}
}
}
and this is what i have in Action Listener
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class Listener implements ActionListener {
JButton[][] gumbi;
public Listener(JButton[][] gumbi) {
this.gumbi = gumbi;
}
public void actionPerformed(ActionEvent e){
JButton gumb = (JButton) e.getSource();
if( gumb.getBackground() == Color.WHITE){
gumb.setBackground(Color.BLACK);
} else if (gumb.getBackground() == Color.BLACK){
gumb.setBackground(Color.WHITE);
}
}
}
Thanks for your time.
Define that int a as static with public access and remove it's definition from within your main method as below:
public class Start {
public static int a = 1;//static since you want to use in static method
public static void main(String[] args){
And then in your listener call, you could use .variable like below:
int number = Start.a;
in your current implementation int a is defined in main method and anything declared in a method will be local to the method, you really have to get the basics right , for now u can define the int a public static int a outside the main method , and then access the variable with the class name reference as shown below
public class Start {
public static int a ;
public static void main() {
//your logic
}
}
public class Listener implements ActionListener {
int temp = Start.a;
}
While I agree with another answer that you can make a static in the main class, there might be a neater solution, even though that it is not exactly what was asked.
Instead of attempting to get the value of a from the main, it makes more sense to send along the value of a in the constructor of Listener.
public class Listener implements ActionListener {
JButton[][] gumbi;
final int a;
public Listener(JButton[][] gumbi, int a) {
this.gumbi = gumbi;
this.a = a;
}
...
In the main method simply change the method that adds the listener as follows:
gumbi[i][j].addActionListener(new Listener(gumbi, a));
I am writing a program which will have multiple windows that will pass a value between them.
Currently I am testing one part of my program that is made out of 1-99 checkboxes. But when I want to check their states by clicking on a button it just doesn't work. Here's where the problem is:
public void actionPerformed(ActionEvent event) {
if(event.getSource() == okay) {
for(int i=0;i<box.length; i++){
for(int j=0;j<box.length; j++){
if((i==0)&&(j==0)) continue;
if(box[i][j].getState())
asdf.matra[i][j]=true;
System.out.println(box[i][j].getLabel() + " is " + asdf.matra[i][j]);
}
}
}
}
here's the main class:
public class asdf {
public static boolean matra[][] = new boolean[10][10];
public static void main(String arg[]) {
for(int ii=0;ii<matra.length; ii++){
for(int jj=0;jj<matra.length; jj++){
matra[ii][jj]=false;
}
}
new JFrameDemo();
}
}
and the other class:
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
public class JFrameDemo extends Frame implements ActionListener, ItemListener {
Checkbox box[][] = new Checkbox[10][10];
Button okay;
JFrameDemo() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
add(makePanel());
pack();
show();
}
private Panel makePanel() {
GridBagConstraints con = new GridBagConstraints();
Panel panel = new Panel();
GridBagLayout gridbag = new GridBagLayout();
panel.setLayout(gridbag);
for(int i=0;i<box.length; i++){
for(int j=0;j<box.length; j++){
if((i==0)&&(j==0)) continue;
box[i][j] = new Checkbox(i+j*10+"");
con.gridx = i;
con.gridy = j;
panel.add(box[i][j],con);
}
}
okay = new Button("Unesi");
con.gridx = 10;
con.gridy = 10;
panel.add(okay,con);
return(panel);
}
public void actionPerformed(ActionEvent event) {
if(event.getSource() == okay) {
for(int i=0;i<box.length; i++){
for(int j=0;j<box.length; j++){
if((i==0)&&(j==0)) continue;
if(box[i][j].getState())
asdf.matra[i][j]=true;
System.out.println(box[i][j].getLabel() + " is " + asdf.matra[i][j]);
}
}
}
}
public void itemStateChanged(ItemEvent event) {
}
public void processWindowEvent(WindowEvent event) {
if(event.getID() == WindowEvent.WINDOW_CLOSING)
System.exit(0);
}
}
The program is running without any errors, but the console isn't giving any results. It is supposed to pass value to the global variable also. I think there's an issues with nested fors.
You are forgetting to add the ActionListener to the button.
okay = new Button("Unesi");
okay.addActionListener(this);