I am trying to make a simple memory game. but I don't know how to set up actionPerformed where when 1 button is pressed, then the program waits for another click and checks if the buttons are the same?
Right now all the code does it create random spots for but[x](set up in other method) and when the button is pressed the button changes to the image to correct image
public void actionPerformed(ActionEvent a) {
for(int x = 0; x < 16; x++) {
if(a.getSource() == but[x]) {
but[x].setIcon(imageicon[x / 2]); //Another method creates the imageicons
}
frame.repaint();
}
}
No need to call repaint() if all you're doing is changing a JLabel or JButton's Icon.
You will need your ActionListener to contain a variable, perhaps an Icon variable, that holds the value of the last button's Icon, and let's call it lastIcon. It will initially hold a value of null.
When the first button is pressed, its icon is displayed, it checks the value of lastIcon. If it is null, it knows that this is the first button, and the lastIcon variable is assigned its icon's value.
When the 2nd button is pressed, it displays its icon, checks it against the last one. If equal, it keeps both buttons displayed. If not equal, it starts a Swing Timer that resets the Icons back to default. Either way, it sets the lastIcon to null.
Note that you do not want to check if one button == another button. You want to either compare their Icons, or else have a separate model class that is distinct from your view, and check if the two buttons are equivalent in your model.
Related
Creating a really basic Memory game using Java Swing. I created my GUI with a list of blank buttons where I set the icon property to none.
My code for some of the buttons is:
private void tbtnCard3ActionPerformed(java.awt.event.ActionEvent evt) {
tbtnCard3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card3Logo.png")));
if(tbtnCard5.isSelected()){
score++;
lblScore.setText(""+score);
}
}
private void tbtnCard4ActionPerformed(java.awt.event.ActionEvent evt) {
tbtnCard4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card7EWaste.png")));
if(tbtnCard7.isSelected()){
score++;
lblScore.setText(""+score);
}
}
private void tbtnCard5ActionPerformed(java.awt.event.ActionEvent evt) {
tbtnCard5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card3Logo.png")));
if(tbtnCard3.isSelected()){
score++;
lblScore.setText(""+score);
}
}
I have about 20 toggle buttons and for example the code above works and the scores go up by 1 when a match is found. So for tbtnCard3, if tbtnCard5 is selected the score goes up by 1. Now my question is how would I make it so that if tbtnCard3 is selected but tbtnCard 5 is not selected, display "Wrong Match". Since im using if Selected I'm not too sure how to display "wrong match" when the case is false. It doesn't make sense to say else ifSelected as no parameters can be put either....
In my opinion, the OPs suggestion is not a good approach. You do not want the listener of one button to be "aware" of some other component unnecessarily. Suppose you have an 8-by-8 grid with toggle buttons. You don't want each toggle button listener to be aware of the other 63 toggle buttons.
I believe there is a much simpler (and cleaner) approach. What you want is for the toggle button listener to register and deregister the toggle when the state of the button changes. Let say, you add the toggle button to or remove from a list (most likely a custom class) where you can trigger some logic when the list size reaches two. Then, depending on the outcome of the comparison, it will count a match (and disable these two toggle buttons in the current state), or will display some message like "Try again" and then toggle the buttons to hide the image.
In pseudocode, this will look something like this:
public class ToggleListener implements ItemListener {
public void actionPerformed (ItemEvent event) {
JToggleButton button = (JToggleButton) event.getSource();
if (event.getStateChange()==ItemEvent.SELECTED) {
// TODO Add the button to your list..
} else {
// remove button
}
}
}
In your Swing application, you can create a single instance of the above listener and add it to every single toggle button. And, as you can see, this listener is only responsible to register and unregister the component associated with the triggered event.
The "List Listener" on the other hand, is responsible to trigger the comparison logic when the size of the list reaches two. So, if you click on the same toggle button over and over again, the only thing the button listener will do is add or remove the button from the list depending on the button's current state. However, once a second button is toggled to reveal its image, the list listener will trigger the comparison logic. I am not 100% sure, but I think you could use JavaFX ObservableList interface or one of its implementing classes to do this. If the ListChangeListener.Change class is not suitable to figure out the size of the list to trigger the logic, you will have to implement this on your own. Regardless, in pseudocode, you need to do something like this:
public void onListChange(Event event) {
if (list.size() == 2 && btn1.getIconName().equals(btn2.getIconName())) {
displayMatchMessage();
btn1.setEnabled(false);
btn2.setEnabled(false);
list.clear(); // you should remove matched items from list manually
} else {
displayMismatchMessage();
btn1.setSelected(false); // flip the card
btn2.setSelected(false); // flip the card
// list.clear(); // you should not need this because the setSelected should trigger the Item Listener which should remove item from list.
}
}
Doing something like this is a much cleaner implementation where the button listener have a single job to do and the "list listener" has another job to do. Neither one encroaches on the other's job.
I have 3 buttons
b1
b2
b3
I want to now have these buttons be pressed in turns.
So turn one I press and turn 2 another person presses.
So after turn two, I will compare the names of the buttons.
b1.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent event ) {
b1.setEnabled(false);
if (!b1.isEnabled() && !b2.isEnabled()) {
//computeWinner(b1.getText(), b2.getText());
} else if(!b1.isEnabled() && !b3.isEnabled()) {
//computeWinner(b1.getText(), b2.getText());
}
}
});
This was what I thought would work, but there are many things wrong with this,
First, since I disable the buttons the second user always has one less option. and second the if statements do not seem to work? how should I compare the
JButton b3 = new JButton ("hello"); <- hello lable of the buttons?
EDIT:
I was able to successfully compare the two buttons. Now my only problem is that for the second player one of the buttons are disabled(how can I capture the first button press and the second without disabling them?). And that after the comparison I don't know how to reset the board to go again. (for a set number of loops.)
Thank you for the help!
The following code will print the label of the button which has been pressed. I hope, you should be able to proceed from here. Feel free to let me know if you face any further issue.
ActionListener actionListener = new ActionListener(){
public void actionPerformed(ActionEvent actionEvent) {
System.out.println(actionEvent.getActionCommand());
}
};
There are several options.
Store the buttons in a map<Integer, String>. the integer would be a count for keeping track of pushes. The string would be the actionCommand of the button pressed.
Store the button actionCommands in a list or array.
In either of the above you can provide appropriate logic to compare the buttons and then reset the arrays or map and count.
Note: The actionCommand defaults to the button label unless it explicitly set.
So I'm trying to make multiple buttons do the same change in color when they are pressed. Each individual press should cycle through a predetermined cycle of colors (White, Red, Green, Yellow, Blue, Black). I could just make a long if-else-statement but for I'm pretty sure there's a better way, I just can't come up with one.
I have already tried "getSource().getBackground()" in the second if-statement but it's not able to get the same variable as the first if-statement does.
public void actionPerformed(ActionEvent e){
if(e.getSource() == btn1){
if(getSource().getBackground() == Color.white)
setBackground(Color.red);
else
setBackground(Color.white);
}
As previously stated I'm trying to minimize the effort here and make it also a bit more organized.
A possible solution would be something like:
Initialize a "button-pressed" counter. So have a variable outside your actionPerformed method and increment it everytime the button is pressed. Add some logic to reset the counter value once it exceeds a certain threshold, i.e. after you cycled through your "last" colour, return to the first color.
Have a switch statement, which would set the background according to the value of the counter (essentially, how many times the button was pressed).
What I would do is make a function that checks and changes background and then pass all my buttons to it.
public void checkAndChangeColor(Object source, Object btn, int bgToCheck, int bgToChange1, int bgToChange2){
if (source == btn) {
if (source.getBackground() == bgToCheck)
setBackground(bgToChange1);
else
setBackground(bgToChange2);
}
}
and then I would call that method on every button.
checkAndChangeColor(e.getSource(), btn, Color.white, Color.red, Color.white);
Make a private inner class that implements ActionListener and have a collection of colors inside it. Override actionPerformed and have an internal count so e.setBackground(colorList.get(count % colorList.size())
I need a button that, when pressed, enables all the other buttons, and changes the name of a label from "Off" to "On", and when pressed again, disables all the buttons and turns the switch to "off" back again, like an on/off switch. The thing is, I can "turn it" on, but I can't turn it back off.
If Swing, then perhaps you will want to place the buttons that you wish to control into an array or an ArrayList<AbstractButton>. That way the ActionListener of the control button can simply iterate through the array or the collection with a for loop, calling setEnabled(true) or false on the buttons. Consider making the controlling button be a JCheckBox or a JToggleButton.
Note, if you use a JToggleButton, then add an ItemListener to it. If you do so, there's no need to use booleans. Just check the state of the ItemEvent passed into the ItemListener's itemStateChanged method. If the getStateChanged() returns ItemEvent.SELECTED, then iterate through your JButton collection enabling all buttons. If it returns ItemEvent.DESELECTED, do the opposite.
Also note as per Byron Hawkins's comment:
You may want to consider that the ItemListener will receive events when the button is programmatically toggled, and also when the user toggles the button. The ActionListener only gets fired on input from the human user. I've often had bugs because I picked the wrong one.
If your button is pressed down and won't pop back up, chances are you have overridden a method in JToggleButton without calling super's version of it. Instead of overriding methods, create an ActionListener and use addActionListener() to attach to the button. When your listener is notified of button actions, check whether the toggle button is up or down and setEnabled() on the other buttons accordingly.
try use this simple code, use the variable as the flag
public int status = 0; //0 = on, 1=off
public void button_clicked()
{
//on button clicked
if(status == 0)
{
//logic here
status = 1;
buttonname.setText("Off");
}
//off button clicked
else if(status == 1)
{
//logic here
status = 0;
buttonname.setText("On");
}
}
you'll need a boolean to represent the state of the button.
In other words, when your button is off (your boolean variable is false), from your onClick listener, you'll call a method "turnButtonOn()" or something of that nature.
If your boolean variable is true, then you'll call a method turnButtonOff()
public void onClick() {
if(buttonOn){
turnOff();
}
else {
turnOn();
}
buttonOn = !buttonOn;
}
I am coding an image puzzle game and one part of the code is to compare the pieces the user has selected to the pieces of the correct image.
Each image piece is already added to a JButton as an ImageIcon.
An identifier is required to differentiate each image piece apart and also for comparision.
I am setting a setName() for each JButton created as the identifier.
The comparison starts when the user releases the mouse after he drags the puzzle pieces from the original 3x3 grid where the shuffled pieces are to the other 3x grid for matching.
I have problems removing the error from the comparison if statement.
I got the comparison idea from this SO thread - link
private JButton[] button = new JButton[9];
private JButton[] waa = new JButton[9];
private String id;
private int cc;
private String id2;
private int cc2;
// setName for each of the 9 buttons in the original 3x3 grid being created
// which stores the shuffled puzzle pieces
for(int a=0; a<9; a++){
button[a] = new JButton(new ImageIcon());
id += Integer.toString(++cc);
button[a].setName(id);
}
// setName for each of the 9 buttons in the other 3x3 grid
// where the images will be dragged to by the user
for(int b=0; b<9; b++){
waa[b] = new JButton();
id2 += Integer.toString(++cc2);
waa[b].setName(id2);
}
// check if puzzle pieces are matched in the correct place
// compare name of original 'button' array button with the name of 'waa' array buttons
button[a].addMouseListener(new MouseAdapter(){
public void mouseReleased(MouseEvent m){
if(m.getbutton().getName().equals (waa.getName())){
}
else{
JOptionPane.showMessageDialog(null,"Wrong! Try Again.");
}
}
}
In your mouseReleased event m.getButton() is returning the mouse button that was clicked. You'll want to do something more like this that will get you closer:
if (m.getComponent().getName().equals(waa.getName())) {
m.getComponent() returns the Component object (your JButton) that the event was fired from. From there you can do the comparison with the getName approach you are using.
There's an additional issue in that your waa variable is an array. I'm not sure how you want to compare them, whether running through the arrays and making sure the index and names match, but that's an additional issue you need to look into.
JButton uses an ActionListener to trigger notifications back to your program to indicate when it's been triggered. This allows the button to respond to different types of event, including the mouse, keyboard and program triggers.
As apart of the action API, you can supply an action command for each button. See JButton#setActionCommand
Basically you would integrate it in a simular way to your mouse listener...
public void actio Performed(ActionEvent evt) {
if (command.equals(evt.getActionCommand()) {...}
}
Depending on your requirements, it might even be easier to use the Action API
The problem you are actually having is waa is an array, therefore, it doesn't have a getName method. I'm also unclear as to why you have two arrays of buttons?