How to run a method from another class when button is pressed? - java

I'm creating a TicTacToe program for a Java project. I'm using swing with a 3x3 panel as the GUI and integrating buttons into each box for the user to click. The problem is, I do not know how to run the WinCondition method (meaning when a user gets 3 in a row). I am not able to call it to the actionPerformed method in the button class, and I don't know where else it would be viable to call.
I have two classes, one is a button class and another is the actual game which creates the panel for the user.
I've tried thinking about where else I could implement it, but I cannot because I do not know another way to execute code when a button is pressed other than the actionPerformed method.
public class TicTacGame extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
JPanel p = new JPanel();
XOButton[] buttons = new XOButton[9];
public TicTacGame() {
super("TicTacToe");
setSize(400,400);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
p.setLayout(new GridLayout(3,3));
for(int i = 0; i < 9; i++) {
buttons[i] = new XOButton();
p.add(buttons[i]);
}
add(p);
setVisible(true);
}
public int winCondition() {
//I have left out the win condition method so this box doesn't get unnecessarily long
}
public static void main(String[] args) {
TicTacGame ttg = new TicTacGame();
}
}
public class XOButton extends JButton implements ActionListener{
/**
*
*/
private static final long serialVersionUID = 1L;
ImageIcon X;
ImageIcon O;
//0 is nothing, 1 is X, 2 is O
int value = 0;
public static int turn = 1;
public XOButton() {
X = new ImageIcon(this.getClass().getResource("X.png"));
O = new ImageIcon(this.getClass().getResource("O.png"));
addActionListener(this);
}
public int getValue() {
return this.value;
}
public void actionPerformed(ActionEvent e) {
if(turn >= 5) {
int win = ttg.winCondition();
}
if(turn % 2 == 0) {
value += 2;
turn++;
}
else {
value++;
turn++;
}
value %= 3;
switch(value) {
case 0:
setIcon(null);
break;
case 1:
setIcon(X);
removeActionListener(this);
break;
case 2:
setIcon(O);
removeActionListener(this);
break;
}
}
}
What I expect is that whenever a button is clicked, the winCondition() method is executed to check if a user won or not.

there's a plenty ways to do that one of them
DON'T
create the win method static, so that you can access from any other class. for more info read comments below
1)you can pass a reference from TicTacGame class into XOButton class in the constructor.. so that you've the access to any other function in TicTacGame class
2)you can use interfaces....etc

Related

Minesweeper Object GUI

I am trying to do a simple Minesweeper game using JFrame, however I am having troubles with the creation of objects. I am creating 96 buttons, some of which get the property of being wrong ("F") and right ("R"):
public class GUIBase extends JFrame {
private JButton button;
private JButton fButton;
public GUIBase() {
super("Minesweeper");
setLayout(new FlowLayout());
//Fields
int position;
for (int i = 0; i < 96; i++) {
position = (int) (Math.random() * 100);
if (position < 80) {
button = new JButton("R");
button.setToolTipText("Is this the correct one?");
add(button);
} else {
fButton = new JButton("F");
fButton.setToolTipText("Is this the correct one?");
add(fButton);
}
}
I then use ActionListener in order to check whether or not the button is correct. If the button is correct, it will get .setEnabled(false), otherwise the game ends:
//Action
Action action = new Action();
button.addActionListener(action);
fButton.addActionListener(action);
}
private class Action implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("Somethin");
if (event.getSource() == button) {
button.setEnabled(false);
} else if (event.getSource() == fButton) {
JOptionPane.showMessageDialog(null, "You lost!");
System.exit(0);
} else {
JOptionPane.showMessageDialog(null, "An error ocurred");
System.exit(0);
}
}
}
Everything in the game turns out as planned, however only the last correct button ("R") and last wrong one ("F") are connected to the ActionListener. The rest of the buttons do not do anything when pressed.
How can I fix this?
The problem is that you only have two variables (attributes of the class GUIBase, specifically), and your are assigning to it each time you create a new button. Hence, you only have a reference to the last buttons.
You need an array of buttons. Let's see:
public class GUIBase extends JFrame {
public final int MAX_BUTTONS = 96;
private JButton[] buttons;
// ...
}
The next step is to create the array itself at the beginning:
public GUIBase() {
super("Minesweeper");
setLayout(new FlowLayout());
this.buttons = new JButton[MAX_BUTTONS];
//Fields
int position;
for (int i = 0; i < buttons.length; i++) {
position = (int) (Math.random() * 100);
this.buttons[ i ] = new JButton("R");
this.buttons[ i ].setToolTipText("Is this the correct one?");
this.add(this.buttons[ i ]);
Action action = new Action();
this.buttons[ i ].addActionListener(action);
}
}
You'll probably need more depth in arrays in order to completely understand the code. Basically, an array is a continuous collection of variables, which you can index by its position, from 0 to n-1, being n the number of positions.
Then you'll probably be able to fill the gaps yourself.
Hope this helps.
One part of your problems is coming from your action listener.
Of course, one part is that your code probably needs a list/array to keep track of all created buttons; but at least right now, you can rework your code without using arrays/list:
private class Action implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("Somethin");
if (event.getSource() instanceofJButton) {
JBUtton clickedButton = (JButton) event.getSource();
String buttonText = clickedButton.getText();
if (buttonText.equals("R") ...
else if (buttonText.equals("F")
You see, the whole point here is: as of now, you just need to know what kind of button was created. And your ActionListener knows which button it was clicked on ...

Error when adding event handler into a JButton to repaint the image inJava GUI

I've created 2 JButtons.One of them has the function of a button and the other handles an image.I want that image to change when this button is clicked.So inserted the method repaint() and added a listener to the first JButton to change the image.When trying to add the listener or the event handler to the first JButton nothing happens.So the image doesn't change.Can anyone show me how can I insert this listener in a way that it works(changes the image when the button is clicked)?Here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
import java.util.Random;
public class Back extends JFrame{
private Random ran;
private int value;
private JButton r;
private JButton c;
public Back(){
super("title");
ran = new Random();
value = nextValue();
setLayout(new FlowLayout());
r=new JButton("ROLL");
add(r);
Icon i=new ImageIcon(getClass().getResource("1.png"));
Icon img=new ImageIcon(getClass().getResource("2.png"));
c= new JButton(i);
if (value==1){
c= new JButton(i);
}
else if(value==2){
c= new JButton(img);
}
add(c);
thehandler hand=new thehandler(this);//konstruktori i handler merr nje instance te Background
r.addActionListener(hand);
c.addActionListener(hand);
}
private int nextValue() {
return Math.abs(ran.nextInt()) % 6 + 1 ;
}
public void roll() {
value = nextValue() ;
repaint() ;
}
public int getValue() {
return value ;
}
private class thehandler implements ActionListener{
private Back d;
thehandler(Back thisone) {
d = thisone ; }
public void actionPerformed(ActionEvent event) {
d.roll() ;
}
}
public static void main(String[] args) {
Back d = new Back() ;
d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
d.getContentPane().setBackground(Color.GREEN);
d.setSize(700,500);
d.setVisible(true);
}
}
So, basically, all your code comes down to here...
public void roll() {
value = nextValue();
repaint();
}
This calculates a new random value and calls repaint. But nothing in your code is effected by value at the point in time it's called.
Instead, you need to update the state of some control, maybe something more like...
public void roll() {
value = nextValue();
Icon i = new ImageIcon(getClass().getResource("1.png"));
Icon img = new ImageIcon(getClass().getResource("2.png"));
if (value == 1) {
c.setIcon(i);
} else if (value == 2) {
c.setIcon(img);
}
}
The next thing I would do is store all your images in some kind of array or List to make it easier to access, then you could simply do something
like...
public void roll() {
value = nextValue();
c.setIcon(listOfImages.get(value - 1));
}
Maybe have a look at Java Swing Timer and Animation: how to put it together for a more detailed example

How do I use the outcome of my actionPerformed method to effect the main method - java

I have a class called Screen containing the actionPerformed method.
I want a different outcome for the different menu items: random, aggressive and human.
This outcome effects the main method, however I am unsure how to link the two...
public class Screen extends JFrame
implements ActionListener {
ActionListener listener;
JMenuItem random = new JMenuItem("Random");
JMenuItem aggressive = new JMenuItem("Aggressive");
JMenuItem human = new JMenuItem("Human");
public Screen(Board board){
//menuBar items
menu.add(random);
random.addActionListener(this);
menu.add(aggressive);
aggressive.addActionListener(this);
menu.add(human);
human.addActionListener(this);
....
//sets up board of buttons and adds actionListener to each.
....
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == random){
}
if(e.getSource() == aggressive){
}
if(e.getSource() == human){
}
//code for the board buttons - nothing to do with the menu.
//But thought it might help
if (numClicks == 0){
JButton piece = (JButton) e.getSource();
String xy = piece.getName();
String x = xy.substring(0,1);
String y = xy.substring(2,3);
FromXInt = Integer.parseInt(x);
FromYInt = Integer.parseInt(y);
System.out.println("From" + " " +FromXInt + "," + FromYInt);
}
else{
JButton piece = (JButton) e.getSource();
String xy = piece.getName();
String x = xy.substring(0,1);
String y = xy.substring(2,3);
ToXInt = Integer.parseInt(x);
ToYInt = Integer.parseInt(y);
System.out.println("To" + " " + ToXInt + "," + ToYInt);
}
numClicks++;
if (numClicks >= 2){
numClicks = 0;
}
return;
}
}
My class which contains the main method:
public class Chess{
public static void main(String [ ] args){
Screen s = new Screen(board);
// my attempt but doesn't work
if (s.actionPerformed(e) == random){
.....
note: I am new to Java and still trying to get my head round the linking of multiple classes.
--------------------The ActionPerformed method also contains events if buttons are clicked but I haven't added that code in because it over complicates things.--
This approach uses a public enum and sets the style variable according to the users menu choice:
package chess;
//...
public class Screen extends JFrame
implements ActionListener {
private JMenuItem random = new JMenuItem("Random");
private JMenuItem aggressive = new JMenuItem("Aggressive");
private JMenuItem human = new JMenuItem("Human");
public enum PlayStyle {Random, Aggressive, Human};
private PlayStyle style;
public Screen(Board board) {
//menuBar items
menu.add(random);
random.addActionListener(this);
menu.add(aggressive);
aggressive.addActionListener(this);
menu.add(human);
human.addActionListener(this);
//....
//sets up board of buttons and adds actionListener to each.
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == random) {
style=PlayStyle.Random;
}
if (e.getSource() == aggressive) {
style=PlayStyle.Aggressive;
}
if (e.getSource() == human) {
style=PlayStyle.Human;
}
//code for the board buttons - nothing to do with the menu.
//....
}
public PlayStyle getStyle(){
return style;
}
}
This is the class that contains the main method:
package chess;
import chess.Screen.PlayStyle;
public class Chess{
public static void main(String [ ] args){
Screen s = new Screen(board);
// this attempt will work
if (s.getStyle()==PlayStyle.Random) {
...
} else if (s.getStyle()==PlayStyle.Aggressive){
...
You are calling a method and it seems that you want to use something that comes back from that method but the method itself returns nothing, i.e. "void". I changed your Screen class so that the method returns something now.
public class Screen extends JFrame
implements ActionListener {
public Source actionPerformed(ActionEvent e) {
....
if(e.getSource() == random){
}
if(e.getSource() == aggressive){
}
if(e.getSource() == human){
}
return e.getSource()
}
The main method will now be able to receive a result from the call and use it.

GuessGame can't get program to output messages

I got the widow and the buttons into the GUI but for the life of me I can't get anything to output. I am suppose to enter a guess, and from a random number the game generates. It is suppose to tell me if I'm too high, too low or correct. Also, if it is not correct it's supposed to tell me if I am warm or cold. If any one could point me in the right direction on this I would be grateful. I don't know what I'm doing wrong on this. I have researched different topics but with the different ways to solve this problem none match what I was looking for.
Here's the code:
//all necessary imports
public class GuessGame extends JFrame
{
private static final long serialVersionUID = 1L;
private JFrame mainFrame;
private JTextField guessField;
private JLabel message1;
private JLabel message2;
private JLabel message3;
private JLabel message4;
private JLabel guessLabel;
private JLabel tooHigh;
private JLabel tooLow;
private JButton guessButton;
private JButton newGame;
private JButton exitButton;
private int randomNum = 0;
private final int MAX_NUM = 1000;
private final int MIN_NUM = 1;
private int guessCount;
private int lastDistance;
public GuessGame()
{
mainFrame = new JFrame();
guessField = new JTextField(4);
message4 = new JLabel("I have a number between 1 and 1000 -- can you guess my number?") ;
guessLabel = new JLabel("Please Enter Your Guess:");
guessButton = new JButton("Guess");
newGame = new JButton("New Game");
exitButton = new JButton("Exit");
Container c = mainFrame.getContentPane();
c.setLayout(new FlowLayout());
c.setBackground(Color.CYAN);
c.add(message4);
c.add(guessLabel);
c.add(guessField);
c.add(guessButton);
c.add(newGame);
c.add(exitButton);
newGame.setMnemonic('N');
exitButton.setMnemonic('E');
guessButton.setMnemonic('G');
mainFrame.setSize(420, 300);//Sets width and height of Window
mainFrame.setVisible(true);//Allows GUI to be visible
mainFrame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
GuessButtonsHandler gHandler = new GuessButtonsHandler();
guessField.addActionListener(gHandler);
ExitButtonsHandler eHandler = new ExitButtonsHandler();
exitButton.addActionListener(eHandler);
NewGameButtonsHandler nHandler = new NewGameButtonsHandler();
newGame.addActionListener(nHandler);
}
class GuessButtonsHandler implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
Random rand = new Random();
int guess = 0;
int currDistance = 0;
boolean correct = false;
guess = Integer.parseInt(guessField.getText());//Converts String to Integer
if(guessCount == 0)
{
lastDistance = MAX_NUM;
}
if(guess >= MIN_NUM && guess <= MAX_NUM)
{
guessCount += 1;
}
if(guess > randomNum)
{
tooHigh.setText("Number To High!!!");
guessCount += 1;
}
else if(guess > randomNum)
{
tooLow.setText("Number To Low!!!");
guessCount += 1;
}
else
{
correct = true;
message2.setText("Correct!!!");
message2.setBackground(Color.GREEN);
guessField.setEditable(false);
}
if(!correct)
{
currDistance = Math.abs(guess - randomNum);
}
if(currDistance <= lastDistance)
{
message3.setText("You are getting warmer!!!");
mainFrame.add(message3).setBackground(Color.RED);
}
else
{
message4.setText("You are getting colder!!!");
mainFrame.add(message4).setBackground(Color.BLUE);
}
lastDistance = currDistance;
randomNum = rand.nextInt(1000) + 1;
}
}
class NewGameButtonsHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Random rand = new Random();
randomNum = rand.nextInt(1000) + 1;
guessCount = 0;
}
}
class ExitButtonsHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
}
public class GuessGameTest {
public static void main(String[] args)
{
new GuessGame();
}
}
You need to:
Add gHandler as a listener to the button too, not only to the text field:
guessField.addActionListener(gHandler);
guessButton.addActionListener(gHandler);
Keeping it in the text field too is a good idea: then the guess can be triggered by pressing enter too, not just clicking the button (this part actually works in your code).
You need to initialize the message labels, and add them somewhere. You have additions commented out, but the initializations are missing.
You don't really need labels for all possible messages. You want to display only a message for too high, too low, or correct guess at a time. Not two or more simultaneously. So one field is enough, just set the correct text.
You have the condition inverted when checking too low numbers.
You generate a new random number after each guess, so the "getting warmer" messages are not very useful. Also you don't need to create a new Random object every time you want a new random number.
Possibly others too, but hopefully these help you forward.

Modifying a JTextField after reading String from another JTextField

Having some problems updating a JTextField in a different class after reading a String from another JTextField. Here's the method in question:
public JTextField buyVowel(playerPlate player)
{
String get = input.getText();
String[] vowels = new String[]{"a","e","i","o","u"};
for(int i =0; i<vowels.length; i++)
{
if(get.equals(vowels[i]))
{
player.pMoney =- 250;
player.playerMoney.setText("$"+player.pMoney);
}
}
return player.playerMoney;
}
playerPlate is a separate class.
I'm using this method to determine what player the program should be modifying:
public playerPlate getCurrentPlayer()
{
if(currentPlayer == 1)
{
return player1;
}
else if(currentPlayer == 2)
{
return player2;
}
else
{
return player3;
}
}
player(s) 1, 2, and 3 are instances of playerPlate.
I want it to be modifying instance variables in this class:
package wheelOfFortune;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class playerPlate extends JPanel
implements ActionListener
{
public String pName;
public int pMoney = 500;
public int currentPlayer;
public JTextField playerMoney;
public playerPlate(String player, Color color, int currentPlayer)
{
setBorder(BorderFactory.createLineBorder(Color.BLACK,2));
setBackground(color);
pName = player;
JTextField playerNames = new JTextField(pName);
playerNames.setBorder(BorderFactory.createLineBorder(Color.BLACK,2));
playerNames.setEditable(false);
playerNames.setFont(new Font("Impact", Font.PLAIN, 24));
playerNames.setHorizontalAlignment(JTextField.CENTER);
playerNames.setBackground(Color.WHITE);
JTextField playerMoney = new JTextField("$"+pMoney);
playerMoney.setBorder(BorderFactory.createLineBorder(Color.BLACK,2));
playerMoney.setEditable(false);
playerMoney.setFont(new Font("Impact", Font.BOLD, 32));
playerMoney.setHorizontalAlignment(JTextField.CENTER);
playerMoney.setBackground(Color.WHITE);
Box b1 = Box.createVerticalBox();
b1.add(playerNames);
b1.add(Box.createVerticalStrut(5));
Box b2 = Box.createHorizontalBox();
b2.add(Box.createHorizontalStrut(60));
Box b3 = Box.createVerticalBox();
b3.add(playerMoney);
b3.add(Box.createVerticalStrut(8));
b2.add(b3);
b1.add(b2);
b1.add(Box.createVerticalStrut(5));
add(b1);
}
public void actionPerformed(ActionEvent e)
{
}
}
Here is the actionPerformed method within the main class:
public void actionPerformed(ActionEvent e)
{
JButton b = (JButton)e.getSource();
if(b==spin)
{
spinWheel(wheelStuff);
repaint();
}
if(b==next)
{
updatePlayer();
repaint();
}
if(b==reset)
{
letterBoard.reset();
updateCat();
repaint();
}
if(b==buyVowel)
{
buyVowel(getCurrentPlayer());
repaint();
}
}
The gist of what I want to happen, is when the user types a vowel into JTextField input, and clicks JButton buyVowel it subtracts $250 from their total money (pMoney). And displays the change on the GUI. After tinkering with this for a couple hours, I honestly have no idea why this isn't working. I keep receiving nullPointerExceptions when trying to use it. Thanks for your help.
Note: everything except for class playerPlate is in the same class. playerPlate is in a separate class.
You're shadowing the variable playerMoney in the constructor of playerPlate. The method buyVowel relies on playerPlate being instantiated when invoking setText, otherwise a NullPointerException will be thrown. Replace
JTextField playerMoney = new JTextField("$"+pMoney);
with
playerMoney = new JTextField("$"+pMoney);
Aside: Java naming conventions indicate that class names start with uppcase letters so use class names such as PlayerPlate.

Categories