ActionListeners in Java - java

Ok so I have two classes in which they are not really associated with each other.
One is the graphic the other in inputs(by terminal using scanners). I want to replace the scanners with a JTextField but I am having a hard time doing so..
Im a bit lost here....
Here is class GUI
//Constructor to create the UI components
public UnoGraphics() {
//JButtons----------------------------
viewCards = new JButton("Move Card");
input = new JTextField(5);
//Creates a canvas and set the properties
canvas = new DrawCanvas();
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH,CANVAS_HEIGHT));
this.setContentPane(canvas);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//This is How I was thinking of implementing my input------------HERE---------------->
input.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inputText = input.getText();
}});//End ActionListener()
this.pack();
this.setTitle("Uno!");
this.setVisible(true);
}//End Constructor
//Custom drawing canvas (designed as inner class). This is were we draw/change the cards
class DrawCanvas extends JPanel {
// Custom drawing codes--------------
#Override
public void paintComponent(Graphics g) {
//Set the background to black
super.paintComponent(g);
setBackground(Color.black);
//cards being drawn-------------------
//buttons and text fields
add(viewCards);
add(input);
}//End PaintComponent()
}//End DrawCavas()
}//End Program
Class Two Inputs with scanners:
public class CommandLinePlayer extends Player
{
//private String inputText;
// constructor
public CommandLinePlayer(String aname)
{
//super aname is from the super class player;
super(aname);
}
// command line player can also say uno. This uses scanner(reads user in puts from keyboard) and the response should be typed in
public boolean sayUno()
{
System.out.println("Would you like to say uno? Yes or No");
Scanner scan = new Scanner(System.in);
String yes = scan.next();
// returns response
//returns yes if the user types yes and ignores the case
return yes.equalsIgnoreCase("Yes");
}
//this method is the choose card of type int takes int one argument of type Card
// command line version (normal player on command line)
//this method takes in the card from your hand and "sends" it to the controller
protected int chooseCard(Card topCard)
{
// display hand
System.out.println("\nHere is the topCard: " + topCard);
System.out.println("Your hand has:");
// loops through the players(commandlineplayer) hand and prints out the players cards. Index could start at 0, but 1 would be the first card
for(int index = 0; index < numOfCards; index ++)
{
System.out.println("Card # " + index + ": " + hand[index]);
}
// choose Card prompts the player to match, or pick a card based on the index, and then press enter.
// if a card does not match the topcard, a key corresponding to any card can be pressed. This would automatically add a
// card to a players hand.
System.out.println("Play a card #. If you don't have a card to play, choose any card # to draw.");
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
return num;
}
// this is the choose color method for the command line player but only if it is a wild card does this method takes place
// command line player can choose a cards color based on the options displayed on the screen.(System.out.println...statements)
public Card.Color chooseColor()
{
// choose a color using scanner
Scanner scanin = new Scanner(System.in);
System.out.println("Choose a color by pressing a number corresponding to your choice:");
System.out.println("Your options are 1.Red 2.Green 3.Yellow 4. Blue");
// the switch corresponds a number (color) to the cases, and returns a chosen card.
int color = 0;
color = scanin.nextInt();
switch (color)
{
case 1: System.out.println("The color you chose is: Red");
return Card.Color.Red;
case 2: System.out.println("The color you chose is: Green");
return Card.Color.Green;
case 3: System.out.println("The color you chose is: Yellow");
return Card.Color.Yellow;
case 4: System.out.println("The color you chose is: Blue");
return Card.Color.Blue;
default: System.out.println("NONE");
}
return Card.Color.None;
}
public class inputListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
//I Was Thinking something like this-----------HERE-----
}
}
}

Here are the relevant chunks of code you need, you should be able to integrate them into your code yourself.
public class Controller {
public void startMethod() {
final UIClass myUI = new UIClass();
myUI.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
handleUIInformation(myUI);
}
}
}
private void handleUIInformation(UIClass myUI) {
String textval = myUI.textField.getText();
// here you do whatever you want with the text
}
}
public class UIClass {
JButton button;
JTextField textField;
public UIClass() {
button = new JButton();
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
button.doClick();
}
}
});
}
public void addActionListener(ActionListener al) {
button.addActionListener(al);
}
}

Related

Every time I pressed Roll(JButton) it left a picture of roll button on

I'm trying to make a snakes and ladders game. It doesn't done yet(no swap turn, no use of ladder and snake) and have so many bug.
But My point is that
I found a problem that make me very curious(Picture Below). It about making a token move. My strategy is that I add a[10][10] array of JPanal(I named it class as Cell) on a big JPanel(I named it class as Board) whose I set its bg as a picture of snakes and ladders game from google and set the layout to gridlayout(10,10). And on every Cell there's one token which is hiding and will only reveal when press the roll button and the output point to that Cell.
This is where the problem happened.
Image of the program when execute
When I press roll button for sometimes
There's a button appear every time I press!(They are not clickable though.)
I know that my start point doesn't even on the left bottom square but where is all that jbutton came from!
This is my main class
public class Main extends JFrame {
TextField text = new TextField();
Dice dice = new Dice();
int tempi = -1, tempj = -1,sum =0;
//Main Method
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Main mPage = new Main();
mPage.setVisible(true);
}
});
}
//Constructor
public Main(){
super("Snakes and Ladders");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(1280,768);
setLocation(400,150);
setLayout(new FlowLayout(FlowLayout.LEFT,30,100));
Board board = new Board();
getContentPane().add(board);
getContentPane().add(dice);
getContentPane().add(text);
//my problem is here.
dice.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int score = Dice.rollDice();
text.setText(String.valueOf(score));
if (tempi != -1 || tempj != -1){
board.cell[9-tempi][9-tempj].fade();
}
if (tempi == -1 && tempj == -1){
sum = sum + score - 1;
}
else sum = sum + score;
tempj = sum%10;
tempi = (sum - tempj)/10;
board.cell[9-tempi][9-tempj].reveal();
}
});
pack();
setMinimumSize(this.getSize());
}
}
This is Cell class
public class Cell extends JPanel implements Cloneable {
private Token pl1 = new Token();
//constructor
public Cell(){
setOpaque(true);
setBackground(new Color(0,0,0,0));
setLayout(new GridLayout(2,2));
this.fade();
this.add(pl1);
}
public void fade(){
pl1.setVisible(false);
}
public void reveal(){
pl1.setVisible(true);
}
}
This is Token class
public class Token extends JLabel {
private BufferedImage image = null;
public Token(){
try {
image = ImageIO.read(new File("C:\\Users\\myacc\\IdeaProjects\\Snakes and Ladders\\src\\Token.png"));
} catch (IOException e) {
e.printStackTrace();
}
Image player = image.getScaledInstance(20,20,Image.SCALE_SMOOTH);
this.setIcon(new ImageIcon(player));
}
}
setBackground(new Color(0,0,0,0));
Don't use backgrounds with transparency. Swing does not know how to paint transparent backgrounds properly.
For full transparency you just make the component non-opaque:
//setOpaque(true);
//setBackground(new Color(0,0,0,0));
setOpaque(false);
If you need semi-transparency, then you need to do custom painting yourself. Check out Background With Transparency for more information on this topic.
Also don't use a TextField. That is an AWT component. Use a JTextField which is the Swing component.

Trouble determining how to make my calculator calculate properly

This is probably the nth time you've received a newbie question regarding calculators, but I just can't figure it out, been working on it for two to three days. The way I have built my calculator at the moment does not suffice and I know I have to start calculating at the time I press the '=' button, but I simply can't figure out how to do so. Due to this reason I have reverted back to my original calculator code, in which it calculates when I press an operation button (like '+') which didn't work, but I was hoping that that would allow me to properly build on it. Here's the code:
package rekenmachine;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.*;
public class Rekenmachine extends JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(300,500);
frame.setLocation(800,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Rekenmachine");
RekenPaneel rekenpaneel = new RekenPaneel();
frame.setContentPane(rekenpaneel);
frame.setVisible(true);
}
private static int getal, totaalGetal;
private boolean optellen, aftrekken, vermenigvuldigen, delen;
public int Optellen(int getal)
{
reset();
optellen = true;
totaalGetal += getal;
getal = 0;
return totaalGetal;
}
public int Aftrekken(int getal)
{
reset();
aftrekken = true;
totaalGetal -= getal;
getal = 0;
return totaalGetal;
}
public int Delen(int getal)
{
reset();
delen = true;
totaalGetal /= getal;
getal = 0;
return totaalGetal;
}
public int Vermenigvuldigen(int getal)
{
reset();
vermenigvuldigen = true;
totaalGetal *= getal;
getal = 0;
return totaalGetal;
}
public int getGetal()
{
return getal;
}
public int getTotaalGetal()
{
return totaalGetal;
}
public void reset()
{
optellen = false;
aftrekken = false;
delen = false;
vermenigvuldigen = false;
getal = 0;
totaalGetal = 0;
}
}
class RekenPaneel extends JPanel
{
JButton knop0, knop1, knop2, knop3, knop4, knop5, knop6, knop7, knop8, knop9,
knopOptel, knopAftrek, knopVermenigvuldigen, knopDelen, knopUitkomst,
knopWissen;
JTextField invoerVak;
JPanel textPaneel, knopPaneel, logoPaneel;
Rekenmachine rekenmachine;
public RekenPaneel()
{
rekenmachine = new Rekenmachine();
setLayout(new BorderLayout());
textPaneel = new JPanel();
knopPaneel = new JPanel();
logoPaneel = new JPanel();
textPaneel.setLayout(new FlowLayout());
knopPaneel.setLayout(new GridLayout(4,4));
logoPaneel.setLayout(new FlowLayout());
Border rand = BorderFactory.createEmptyBorder(10, 10, 10, 10);
knop0 = new JButton("0");
knop0.addActionListener(new knop0Handler());
knop1 = new JButton("1");
knop1.addActionListener(new knop1Handler());
knop2 = new JButton("2");
knop2.addActionListener(new knop2Handler());
knop3 = new JButton("3");
knop3.addActionListener(new knop3Handler());
knop4 = new JButton("4");
knop4.addActionListener(new knop4Handler());
knop5 = new JButton("5");
knop5.addActionListener(new knop5Handler());
knop6 = new JButton("6");
knop6.addActionListener(new knop6Handler());
knop7 = new JButton("7");
knop7.addActionListener(new knop7Handler());
knop8 = new JButton("8");
knop8.addActionListener(new knop8Handler());
knop9 = new JButton("9");
knop9.addActionListener(new knop9Handler());
knopOptel = new JButton("+");
knopOptel.addActionListener(new knopOptelHandler());
knopAftrek = new JButton("-");
knopAftrek.addActionListener(new knopAftrekHandler());
knopVermenigvuldigen = new JButton("*");
knopVermenigvuldigen.addActionListener(new knopVermenigvuldigenHandler());
knopDelen = new JButton("/");
knopDelen.addActionListener(new knopDelenHandler());
knopUitkomst = new JButton("=");
knopUitkomst.addActionListener(new knopUitkomstHandler());
knopWissen = new JButton("C");
knopWissen.addActionListener(new knopWissenHandler());
invoerVak = new JTextField(25);
invoerVak.setHorizontalAlignment(invoerVak.RIGHT);
invoerVak.setEditable(false);
invoerVak.setBackground(Color.WHITE);
textPaneel.add(invoerVak);
knopPaneel.add(knop7);
knopPaneel.add(knop8);
knopPaneel.add(knop9);
knopPaneel.add(knopDelen);
knopPaneel.add(knop4);
knopPaneel.add(knop5);
knopPaneel.add(knop6);
knopPaneel.add(knopVermenigvuldigen);
knopPaneel.add(knop1);
knopPaneel.add(knop2);
knopPaneel.add(knop3);
knopPaneel.add(knopOptel);
knopPaneel.add(knop0);
knopPaneel.add(knopWissen);
knopPaneel.add(knopUitkomst);
knopPaneel.add(knopAftrek);
add(textPaneel, BorderLayout.NORTH);
add(knopPaneel, BorderLayout.CENTER);
add(logoPaneel, BorderLayout.SOUTH);
}
class knop0Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "0");
}
}
class knop1Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "1");
}
}
class knop2Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "2");
}
}
class knop3Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "3");
}
}
class knop4Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "4");
}
}
class knop5Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "5");
}
}
class knop6Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "6");
}
}
class knop7Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "7");
}
}
class knop8Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "8");
}
}
class knop9Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "9");
}
}
class knopOptelHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Optellen(invoerGetal);
invoerVak.setText("");
}
}
class knopAftrekHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Aftrekken(invoerGetal);
invoerVak.setText("");
}
}
class knopVermenigvuldigenHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Vermenigvuldigen(invoerGetal);
invoerVak.setText("");
}
}
class knopDelenHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Delen(invoerGetal);
invoerVak.setText("");
}
}
class knopUitkomstHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText("" + rekenmachine.getTotaalGetal());
rekenmachine.reset();
}
}
class knopWissenHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
rekenmachine.reset();
invoerVak.setText("");
}
}
}
What it basically does is look like a calculator, all buttons work, yet the way it calculates is way off, if at all. I think what I need to do is save a number, when I press + it should add the next number, if I press - it should substract the next number, if I press * it should multiply by the next number and if I press / it should divide by the next number, then when I press = it should show the result, yet I have no idea how to do that.
Should it be done with an arraylist? If so, how could I properly save the result? I mean, using it with two numbers isn't that hard, you just save two numbers and do something with them, then show the result, but a person doesn't always use just two numbers.
To explain the problem I'm having more clearly: for example, when I enter '50' and then press '+' it SHOULD convert "50" to getal = 50 and start the Optellen method, then totaalGetal should become 50, it then empties the textfield. If I then add '3', it should say 53 when I press '=' yet it still shows 50 if I'm lucky. To solve that I assume I have to make the calculation WHEN I press '=' but I don't know how to save/calculate numbers before having done that.
Can anybody tell me what to do before I've lost all my hair? :P
When you click on the +, you're calling this:
knopOptel.addActionListener((ActionEvent e) ->
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.addition(invoerGetal);
invoerVak.setText("");
});
But when you click on +, you're not doing the calculation yet! What you should be doing is:
The user type a number
The user click on + (for example)
In your ActionListener, you read the number on the screen, you store it in getal, you clear the screen, and you set your boolean optel to true
The user types another number
The user click on equal
In your equal Listener, you read the number you read the number on the screen, and depending on the flag (optel in the example), you calculate the result
you display the result
So indeed, the calculation is done when you press equal.
A small code example:
knopOptel.addActionListener((ActionEvent e) ->
{
int invoerGetal = Integer.parseInt(invoerVak.getText()); // get the number
calculate(invoerGetal); //sets totalNumber to what it should be by looking at the flags
invoerVak.setText(totalNumber); // we write the temporary result
additionFlag = true; // next number must be added
});
And your calculate function should just be something like:
private void calculate(int aInvoerGetal) {
if (addition)
totalNumber += aInvoerGetal;
else if (substract)
totalNumber -= aInvoerGetal;
else if (divide)
totalNumber /= aInvoerGetal;
else if (multiply)
totalNumber *= aInvoerGetal;
resetFlags();
}
TO GO FURTHER:
Now, if you want to support multiple caculations (5+5+5+3), it's easy. When you click on +, -, *, /, you first call the equalActionListener.
This way, you get this kind of sequence:
5, + // ==> equal called ==> 5 (because the flags are all false) ==> flag + to true
10, + // ==> equal called ==> 15 because 5 in memory and + flag was on. + flag goes off, then on again (because you pressed + again)
4, = // ==> equal called ==> 19
When developing something, you have to think first how you want to solve a problem. Work from there by designing a solution. If you have a programmable solution, implement it. The UI may come later. That's a core skill that a developer should have.
1) You want to have a calculator that support +, -, / and *. The output should be shown if "=" is clicked.
2) Think with classes. That concept may be new for you, but you will discover later from. Your main class that does the calculations is Rekenmachine. (From a design perspective, it should be a stand alone class, but that's not important now). You need to separate it from your UI layer.
Your class supports the actions that you have implemented with the UI. That's good. But I also see things that shouldn't be there
public int Vermenigvuldigen(int getal)
{
reset(); // reset the calculator ?
vermenigvuldigen = true; // purpose ?
totaalGetal *= getal;
getal = 0; // resetting argument getal ?
return totaalGetal;
}
Here, I'm not sure why you're calling reset() because what it does is
public void reset()
{
optellen = false;
aftrekken = false;
delen = false;
vermenigvuldigen = false;
getal = 0;
totaalGetal = 0;
}
When reading the above method, you see that it resets the value that you tried to add on. Of course your calculation would go wrong because you're erasing previous data... resetting everything back to initial state. I also don't understand the setting to "true" or "false" on the actions. Perhaps for the UI? That is not required.
Make it simple:
When creating Rekenmachine, set the variable totaalGetal to 0 as default. That variable holds the value of your calculations performed so far. That's the start. When you have an addition, use
public void add(int getal) {
totaalGetal+= getal; // means totaalGetal = totaalGetal + getal.
}
Before calling add() you have to parse the string to an integer. This can be done in the button action:
class knop1Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// get input
String input = invoerVak.getText();
// convert
int converted = convertToInt(input);
// instruct myRekenmachine to add the value
myRekenmachine.add(converted);
}
}
Important note ... use concise naming ... "knop1handler" is difficult to read. Use "addButtonHandler" to indicate that this class handles the add button.
convertToInt is a method that reads in a String and returns with an integer. You have to implement that yourself. myRekenmachine is an instance of your Rekenmachine class.
This above is for addition. Implement the same for other operands. If you want to adjust the UI, do that in the handler.
Now, when you press =, just return the totaalGetal value.
PS: Not sure, but ask if you are allowed to write names in English. My native language is Dutch, but during my CS courses, I am allowed to program completely in English. Please try to ask it because English is the main language in IT world if you're aiming for a career in IT.
Wesley, did you think about what you wanted the calculator to do before you started coding? e.g. would it support brackets, sin/cos, memory. Did you think about how logically these functions would work and then think of how they could be implemented in Java? A few flow charts and some pesudocode can go a long way when you're starting out in a new language if only to help you comprehend what it is you are trying to do.
BTW I know it's tempting to start with the GUI code and move into the logic of the application but it is usually better to start with the logic and then move onto the GUI. You can hard code the values for inputs and see if the functionaly behaves as expected and then introduce parameters with values passed in from else where.
EDIT
I think I know why your + key is not working. The reset() method is setting getal and totalGetal to 0 before adding them. 0 + 0 is 0.
knopOptel = new JButton("+");
knopOptel.addActionListener(new knopOptelHandler());
class knopOptelHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Optellen(invoerGetal);
invoerVak.setText("");
}
}
public int Optellen(int getal)
{
reset();
public void reset()
{
optellen = false;
aftrekken = false;
delen = false;
vermenigvuldigen = false;
getal = 0;
totaalGetal = 0;
}
optellen = true;
totaalGetal += getal;
getal = 0;
return totaalGetal;
}

Unable to use for loop to change which JLabel is currently being affected

I am attempting to use a forloop to be able to change which jlabel is being affected, as for they all perform the same function, and have the same name other than the numerical value at the end of each name.
Essentially, I use a drag and drop transfer handler to create a food web game. I want to randomize the game to three different food webs that may appear. The randomization is fine and all, but I am unknowledgable of how to use a loop to determine which JLabel's icon is being set. Since I am using generally all the same name for each individual JLabel that has an icon that will change based on which themed food web was randomly selected, I am wanting to know how to make the loop change which JLabel is being selected, as for I get a syntax error from attempting to do the "selection(i+1)".
private static int randomNumber(){
return(int) (Math.random() * (3 - 1 + 1) + 1);
}
private void generateQuiz(){
switch(randomNumber()){
case 1: //the for loop changes each available selection based on each element in the foor loop.
for(int i = 0; i < consumers1.size(); i++){
selection(i+1).setIcon(new ImageIcon(getClass().getResource(
"/resources/quiz/"+consumers1.get(i)+".png")));
}
break;
case 2:
break;
case 3:
break;
want: change each of these selection boxes auto-magically using a for loop rather than typing each individual thing manually for each case
EDIT: This is the rest of the general code around this problem,
private String[] producers = {"grass", "plankton", "berries"};
private ArrayList<String> consumers1 = new ArrayList();
private ArrayList<String> consumers2 = new ArrayList();
private ArrayList<String> consumers3 = new ArrayList();
//mouselistener to handle all image move-ability
MouseListener mouseListener = new MouseListener() {
#Override public void mouseClicked(MouseEvent e) {}
//a mouselistener for that each img has the ability to be moved into spots
#Override
public void mousePressed(MouseEvent e) {
JComponent jc = (JComponent)e.getSource();
TransferHandler th = jc.getTransferHandler();
th.exportAsDrag(jc, e, TransferHandler.COPY);
// System.out.println(producers1.getIcon());
}
#Override public void mouseReleased(MouseEvent e) {}
#Override public void mouseEntered(MouseEvent e) {}
#Override public void mouseExited(MouseEvent e) {}
};
/**
* Creates new form Quiz
*/
public Quiz() {
initComponents();
//sets the jframe to the center of the screen
setLocationRelativeTo(null);
//changes how the jframe closes
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent windowEvent) {
//confirm dialog to ensure user wants to close, if not return
int confirm = JOptionPane.showConfirmDialog(null,
"A quiz is currently inprogress. "
+ "\nAll unsubmitted quizs will not be saved!"
+ "\nDo you wish to exit?",
"Exit",
JOptionPane.YES_NO_OPTION);
if (confirm == JOptionPane.YES_OPTION){
System.exit(0);
}
}
});
//random algorithm; t1 = x, tn = (tn-1) + xn
//<--- RANDOM QUIZ GENERATION --->
//add all the image names to array lists
Collections.addAll(consumers1, "goat", "rabbit", "jackal", "wildcat",
"lion");
Collections.addAll(consumers2, "fish", "mussel", "bird", "octopus",
"human");
Collections.addAll(consumers3, "butterfly", "grasshopper", "frog",
"spider", "snake");
generateQuiz();
// end of quiz generaiton
//<--- DRAG AND DROP ADDITIONS LISTENERS AND TRANSFER HANDLERS --->
//adds mouse listener to be able to drag and drop the imgs in the seleciton boxes
selection1.addMouseListener(mouseListener);
selection2.addMouseListener(mouseListener);
selection3.addMouseListener(mouseListener);
selection4.addMouseListener(mouseListener);
selection5.addMouseListener(mouseListener);
selection6.addMouseListener(mouseListener);
//creates transfer handlers to bea ble to drag and drop the images in the frame
TransferHandler th = new TransferHandler("icon");
selection1.setTransferHandler(th);
selection2.setTransferHandler(th);
selection3.setTransferHandler(th);
selection4.setTransferHandler(th);
selection5.setTransferHandler(th);
selection6.setTransferHandler(th);
producer.setTransferHandler(th);
consumer1.setTransferHandler(th);
consumer2.setTransferHandler(th);
consumer3.setTransferHandler(th);
consumer4.setTransferHandler(th);
consumer5.setTransferHandler(th);
//<--- END OF DRAG AND DROP ADDITIONS LISTENERS AND TRANSFER HANDLERS --->
}
private static int randomNumber(){
return(int) (Math.random() * (3 - 1 + 1) + 1);
}
private void generateQuiz(){
switch(randomNumber()){
case 1:
for(int i = 0; i < consumers1.size(); i++){
selection(i+1).setIcon(new ImageIcon(getClass().getResource(
"/resources/quiz/"+consumers1.get(i)+".png")));
}
break;
case 2:
break;
case 3:
break;
}
}
P.S.: It's made in netbeans gui builder for a school assignment so it'x declared in the automatic generated code by neatbeans
Ah, "selection..." is simply a variable name.
When the Java program is compiled, most variable names are replaced by pointers to memory locations, so you can't assemble a string at run time and invoke the corresponding variable. (You could make them public and use Reflection but it would be absolutely wrong here).
Here the simplest way to do what you are trying is the following:
JLabel[] selections={
selection1,
selection2,
selection3,
selection4,
selection5,
selection6
};
and then use selections[i] instead of selection(i+1).

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.

Swing threading issue?

I have a game that I wrote with Java that runs perfectly on command line. However, I've been building a GUI for it and have been changing it so it runs on the GUI but I'm having issues. It's a hangman game that allows the player to guess letters to try to guess the hangman word. If the player makes a correct guess, the game displays a certain message, and if the player makes an incorrect guess, the game displays a different message. The game stops working after I've made two guesses using the GUI version though... I've been trying to fix it for a couple of days but no luck...I've tried calling javax.swing.SwingUtilities.invokeLater but it's still giving me issues.
Any help would be appreciated, heres the code (p.s. I'm still in the process of moving stuff from command line to GUI):
import java.util.ArrayList;
import java.util.Scanner;
public class HangmanTwo {
private String[] wordList = {"apple", "orange"};
private String chosenWord;
private String playerGuess;
private int numberOfIncorrectGuesses = 0;
private boolean playerWon = false;
private boolean playerPlaying = false;
public static String uInput1;
private boolean start = false;
private ArrayList<String> lettersOfChosenWord;
private ArrayList<String> incorrectGuessArrayList2 = new ArrayList<String>();
private ArrayList<String> underScores;
private boolean showHangman = false;
HangmanGuiGui hh = new HangmanGuiGui();
//Print game instructions to player
void printGameInstructions() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
hh.buildGui();
hh.textFieldSouth.requestFocus();
hh.textAreaCenter.append("Welcome to Hangman! \n");
hh.textAreaCenter.append("To play, type in a letter as your guess, then press ENTER! \n");
hh.textAreaCenter.append("If you think you know the word, type in the whole word and see if you got it right! \n");
hh.textAreaCenter.append("But be careful! Guessing the word incorrectly will cost you a limb! \n");
hh.textAreaCenter.append("To start playing, type 'start' and press ENTER. \n");
}
});
}
//Ask player if they want to start the game
void askToStart() {
uInput1 = "waitingforinput";
while (!start) {
if(uInput1.equals("waitingforinput")) {
} else if ((uInput1).equals("start")) {
start = true;
uInput1 = "waitingforInput";
} else {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
hh.textAreaCenter.append("Please type the word 'start' then press the ENTER key to begin playing. \n");
}
});
uInput1 = "waitingforinput";
}
}
}
//Game picks random word from word list
void pickRandomWord() {
int lengthOfWordList = wordList.length;
int pickRandomWord = (int) (Math.random() * lengthOfWordList);
chosenWord = wordList[pickRandomWord];
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
hh.textAreaCenter.append("The word is " + chosenWord.length() + " letters long\n");
}
});
}
//Make an arraylist to hold each letter of the chosen word at each index
void makeArrayListOfChosenWord(){
lettersOfChosenWord = new ArrayList<String> ();
for (int i = 0; i < chosenWord.length(); i++) {
lettersOfChosenWord.add(chosenWord.substring(i, i+1));
}
}
//Make an arraylist of underscores that holds as
//many underscores as letters in the chosen word
void makeArrayListUnderScore(){
underScores = new ArrayList<String>();
for (int i = 0; i < chosenWord.length(); i++) {
underScores.add("_");
}
for (int i = 0; i < underScores.size(); i++) {
//hh.textAreaWest.append((underScores.get(i)).toString());
//show the underscores in the text area
}
}
//get a guess from the player
void getPlayerGuess() {
boolean getGuess = true;
uInput1 = "waitingforinput";
while (getGuess) {
if (uInput1.equals("")) {
//javax.swing.SwingUtilities.invokeLater(new Runnable() {
//public void run() {
hh.textAreaCenter.append("Please guess a letter\n");
//}
//});
uInput1 = "waitingforinput";
} else if (uInput1.equals("waitingforinput")) {
} else {
playerGuess = uInput1;
//javax.swing.SwingUtilities.invokeLater(new Runnable() {
//public void run() {
hh.textAreaCenter.append(playerGuess + "\n");
//}
//});
getGuess = false;
}
}
}
//if the player wins, set the variable playerWon to true
void setPlayerWon(boolean a) {
playerWon = a;
}
//start the game and play it
void playGame() {
playerPlaying = true;
while (playerPlaying && !playerWon) {
getPlayerGuess();
if (playerGuess.equals(chosenWord)) {
playerPlaying = false;
wordWasGuessed();
}else if (numberOfIncorrectGuesses < 6) {
checkPlayerGuess();
if (playerWon) {
playerPlaying = false;
wordWasGuessed();
} else if (numberOfIncorrectGuesses == 6) {
playerPlaying = false;
gameOver();
}
}
}
}
//check the player's guess and see if its correct or not
void checkPlayerGuess(){
//update number of incorrect guesses
if (lettersOfChosenWord.contains(playerGuess)) {
System.out.println("Correct guess!");
if (!showHangman) {
displayNoose();
}
displayHangman();
replaceUnderScoreWithLetter();
if (!underScores.contains("_")) {
setPlayerWon(true);
}
} else if (!lettersOfChosenWord.contains(playerGuess)) {
checkIncorrectGuessArrayList();
}
}
//check the incorrectguess array list and add incorrect letters to it
void checkIncorrectGuessArrayList() {
if (incorrectGuessArrayList2.contains(playerGuess)) {
System.out.printf("You already guessed %s, try again!", playerGuess);
} else if (!incorrectGuessArrayList2.contains(playerGuess)) {
if (numberOfIncorrectGuesses < 6) {
System.out.println("You guessed wrong, try again!");
incorrectGuessArrayList2.add(playerGuess);
++numberOfIncorrectGuesses;
displayHangman();
printArrayListUnderScore();
}
}
}
//replace the underscores with a letter
void replaceUnderScoreWithLetter() {
while (lettersOfChosenWord.contains(playerGuess)) {
int indexOfPlayerGuess = lettersOfChosenWord.indexOf(playerGuess);
underScores.set(indexOfPlayerGuess, playerGuess);
lettersOfChosenWord.set(indexOfPlayerGuess, "_");
incorrectGuessArrayList2.add(playerGuess);
}
printArrayListUnderScore();
}
//show the underscores to the player
void printArrayListUnderScore() {
for (int j = 0; j < underScores.size(); j++) {
System.out.print((underScores.get(j)).toString());
}
}
void resetAllValues(int resetNumberIncorrectGuesses, boolean hangmanshow) {
numberOfIncorrectGuesses = resetNumberIncorrectGuesses;
lettersOfChosenWord.removeAll(lettersOfChosenWord);
incorrectGuessArrayList2.removeAll(incorrectGuessArrayList2);
underScores.removeAll(underScores);
showHangman = hangmanshow;
}
void displayNoose(){
System.out.println(" ___,");
System.out.println(" l ");
System.out.println(" l");
System.out.println("_l_");
}
//Display a growing hangman with each incremental wrong guess
void displayHangman(){
switch (numberOfIncorrectGuesses) {
case 1: firstWrongGuess();
showHangman = true;
break;
case 2: secondWrongGuess();
break;
case 3: thirdWrongGuess();
break;
case 4: fourthWrongGuess();
break;
case 5: fifthWrongGuess();
break;
case 6: sixthWrongGuess();
break;
}
}
void firstWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l");
System.out.println("_l_");
}
void secondWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l l");
System.out.println("_l_");
}
void thirdWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l");
System.out.println("_l_");
}
void fourthWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l\\");
System.out.println("_l_");
}
void fifthWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l\\");
System.out.println("_l_/");
}
void sixthWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l\\");
System.out.println("_l_/ \\");
}
//what happens if the chosenWord was guessed
void wordWasGuessed() {
hh.textAreaCenter.append("******\n");
hh.textAreaCenter.append("GOOD JOB! YOU GUESSED THE WORD!\n");
hh.textAreaCenter.append("You wanna play again? (y/n)\n");
resetGame(0, false, false);
boolean playAgain = false;
while (!playAgain) {
Scanner s = new Scanner(System.in);
String userInput = s.next();
if (userInput.equals("y")) {
playAgain = true;
resetAllValues(0, false);
startGame();
} else if (userInput.equals("n")) {
playAgain = true;
System.out.println("Ok...See you next time!");
} else {
System.out.println("please type y or n, then press enter!");
}
}
}
//what happens when the player loses and game is over
void gameOver() {
System.out.println("Aww you lost... the word was " + chosenWord);
System.out.println("You wanna play again? (y/n)");
resetGame(0, false, false);
boolean playAgain = false;
while (!playAgain) {
Scanner s = new Scanner(System.in);
String userInput = s.next();
if (userInput.equals("y")) {
playAgain = true;
resetAllValues(0, false);
startGame();
} else if (userInput.equals("n")) {
playAgain = true;
System.out.println("Ok...See you next time!");
} else {
System.out.println("please type y or n, then press enter!");
}
}
}
//reset the game
void resetGame(int resetNumberIG, boolean resetPlayerWon, boolean resetPlayerPlaying) {
numberOfIncorrectGuesses = resetNumberIG;
playerWon = resetPlayerWon;
playerPlaying = resetPlayerPlaying;
}
void startGame() {
pickRandomWord();
makeArrayListOfChosenWord();
makeArrayListUnderScore();
}
public static void main(String[] args) throws InterruptedException {
HangmanTwo h = new HangmanTwo();
h.printGameInstructions();
h.askToStart();
if (h.start == true) {
h.startGame();
h.playGame();
}
}
}
And GUI
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class HangmanGuiGui {
TextFieldSouthHandler tfsHandler = new TextFieldSouthHandler();
ButtonEnterHandler beHandler = new ButtonEnterHandler();
JFrame frame = new JFrame("Hangman");
JLabel label = new JLabel("Welcome to Hangman");
public JTextArea textAreaCenter = new JTextArea();
JTextField textFieldSouth = new JTextField();
JScrollPane scrollPane = new JScrollPane();
JPanel panelWest = new JPanel(new BorderLayout());
JPanel subPanelWest = new JPanel();
JTextArea textAreaWest = new JTextArea();
JPanel panelSouth = new JPanel(new BorderLayout());
JButton buttonEnter = new JButton("Enter");
//Icon aba = new ImageIcon(getClass().getResource("hangman1.jpg"));
//JLabel picLabel = new JLabel(aba);
JPanel panelEast = new JPanel();
void buildGui() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textAreaCenter.setEditable(false);
textFieldSouth.addKeyListener(tfsHandler);
textAreaWest.setEditable(false);
buttonEnter.addActionListener(beHandler);
panelSouth.add(BorderLayout.CENTER, textFieldSouth);
panelSouth.add(BorderLayout.EAST, buttonEnter);
//subPanelWest.add(picLabel);
JPanel panelwesteast = new JPanel();
JPanel panelwestwest = new JPanel();
JPanel panelwestsouth = new JPanel();
panelWest.add(BorderLayout.SOUTH, panelwestsouth);
panelWest.add(BorderLayout.EAST, panelwesteast);
panelWest.add(BorderLayout.WEST, panelwestwest);
panelWest.add(BorderLayout.NORTH, subPanelWest);
panelWest.add(BorderLayout.CENTER, textAreaWest);
scrollPane.getViewport().setView (textAreaCenter);
frame.getContentPane().add(BorderLayout.NORTH, label);
frame.getContentPane().add(BorderLayout.CENTER, scrollPane);
frame.getContentPane().add(BorderLayout.SOUTH, panelSouth);
frame.getContentPane().add(BorderLayout.WEST, panelWest);
frame.getContentPane().add(BorderLayout.EAST, panelEast);
frame.setSize(800, 600);
frame.setVisible(true);
}
private class TextFieldSouthHandler implements KeyListener {
public void keyPressed(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.VK_ENTER) {
//boolean bee = javax.swing.SwingUtilities.isEventDispatchThread();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
HangmanTwo.uInput1 = textFieldSouth.getText();
textFieldSouth.setText("");
}
});
}
}
public void keyTyped(KeyEvent event) {
}
public void keyReleased(KeyEvent event) {
}
}
private class ButtonEnterHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
HangmanTwo.uInput1 = textFieldSouth.getText();
textFieldSouth.setText("");
textFieldSouth.requestFocus();
}
});
}
}
}
/*javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
}
}); */
You have literally translated a main-loop structure, which is perfectly suitable for a command line application, to swing. Then you immerse yourself in infinite loops in your main thread looking for a change in shared variables. This conflicts with the way Swing manages things, the main thread of the application is paramount for Swing to manage its repainting and its event handling, and your code is competing against it for the processor. I think we can think of a better design for a Swing application.
You have 2 possibilites:
You can take your original command line program and just replace any reading you take from the keyboard for a modal dialog asking for a letter. This way you respect your sequential design and avoid multi-threading problems.
Or my favorite: I suggest that you consider completely changing your sequential design to a responsive one. In this case, you renounce to a main loop, just show a JPanel inside a JFrame with your UI, and then just write responsive event handlers to each button or change in your inputs. You should just store the state of your program into the main class and your event handlers interact with it.
By the way, whatever your decision, I strongly advise you to remove all that invokeLater(new Runnable() ...), being innecessary and maybe dangerous (you can be introducing race conditions between your event handlers by doing it)
In order to avoid major headaches, you should redesign the control of your application.
Without a GUI, you directly control the process: wait for input, process, show results, repeat.
With a GUI, you show a window and then do nothing. When the user inputs something, the GUI invokes one of your callback methods, and there you react according to your current state.
So: don't try to have a control thread, it's very easy to have a lot of threading problems. Set some variables which tell you what is the current game state (wait for "START" keyword, wait for guess, finished...), and update them when the user does something.

Categories