Swapping icons of 2 jbutton - java

I want to change the icon of 2 Jbuttons by selecting one and then the next to swap their icons. Something like candy crush or bejeweled.
I want to use action listener to accomplish this, how should i go about doing it?
this is the gui of my program:
public class UI implements Runnable {
private JFrame _frame;
private Model _model;
private ArrayList<JButton> _tiles;
public void run() {
_model = new Model();
_frame = new JFrame();
_frame.setLayout(new GridLayout(5,5));
_tiles = new ArrayList<JButton>();
for (int i=0; i<25; i++) {
JButton tile = new JButton();
tile.setBackground(Color.white);
//this just pick out random icon file from a folder
tile.setIcon(_model.randomIcon());
tile.addActionListener(new ButtonBorderHandler(_model,tile));
//this is the actionlistener that i want to implement the swap on
tile.addActionListener(new ButtonSwapHandler();
_tiles.add(tile);
}
i've tried doing it like so
public class ButtonSwapHandler implements ActionListener{
JButton _button1;
JButton _button2;
Model _model;
UI _ui;
public ButtonSwapHandler(UI u,Model m, JButton b1, JButton b2){
_model=m;
_button1=b1;
_button2=b2;
_ui =u;
}
#Override
public void actionPerformed(ActionEvent e) {
//this line should give me the position of the first button i press
int i = _ui.getTiles().indexOf(e.getSource());
//this is the part where i dont know how to keep going
//i want to know where is the 2nd button that i clicked
int j = _ui.getTiles().indexOf(e.
// this is the method i wrote to make the swap
// it just the Collections.swap(tile,positionOfButton1,postionOfButton2)
_model.swap(ui._tile,i,j);
}

Your logic needs little clarity. You are creating a 5x5 grid, where you are populating the buttons.
For example like this:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
But, when you are clicking on a button, how do you ensure the direction of swap? Say, if the user clicks on button 7, which adjacent button of 7 should be selected for swapping?
So, the missing piece of your logic is the direction.
For example:
If the swap always happens with immediate left button, you can calculate the swap button like indexOf(selectedButton)-1. Again, the swap may be happening on conditional basis only if that row in that two dimensional grid has immediate left button.
Update:
If the action is supposed to happen only after clicking two buttons, then you need to create one more class which actually keeps track of number of buttons clicked then swaps when count==2.
Following is a modified example:
public class ButtonClicksCounter {
static ArrayList<JButton> _buttonsClicked = new ArrayList<JButton>();
public static void addButton(JButton btn) {
_buttonsClicked.add(btn);
}
public static int getButtonClicksCount() {
return _buttonsClicked.size();
}
public static void clearButtonClicksCount() {
_buttonsClicked.clear();
}
public ArrayList<JButton> getButtonsClicked() {
return _buttonsClicked;
}
}
public class ButtonSwapHandler implements ActionListener{
JButton _button;
Model _model;
UI _ui;
public ButtonSwapHandler(UI u, Model m, JButton b1){
_model=m;
_button=b1;
_ui =u;
}
#Override
public void actionPerformed(ActionEvent e) {
//Add the button
ButtonClicksCounter.addButton((JButton)e.getSource());
//Check if count==2
if(ButtonClicksCounter.getButtonClicksCount()==2) {
ArrayList<JButton> buttonsToSwap = ButtonClicksCounter.getButtonsClicked();
//Get positions
int i = _ui.getTiles().indexOf(buttonsToSwap[0]);
int j = _ui.getTiles().indexOf(buttonsToSwap[1]);
//Swap
_model.swap(ui._tile,i,j);
//Clear selection
ButtonClicksCounter.clearButtonClicksCount();
}
}

Related

Two different buttons in one Panel in my own Component

I'm trying to create JPanel with two different buttons which one of them increasing and second decreasing size of text or window. I have class with button declaration. Everything is working when I put these buttons on JFrame separately.
I don't know how to get Action Listener in JPanel of each buttons. All I possibly do is listener of mouse click on JPanel...
Could you help me? I'm really begginer with coding so be polite please :]
public class ButtonMy extends Component {
private ButtonIncrease increase;
private PropertyChangeSupport propertyChangeSupport;
public ButtonMy() {
setPreferredSize(new Dimension(30,30));
kolor = Color.blue;
setForeground(kolor);
propertyChangeSupport = new PropertyChangeSupport(this);
increase = ButtonIncrease.Powieksz;
}
public ButtonIncrease getIncrease() {
return increase;
}
public void setIncrease(ButtonIncrease increase) {
ButtonIncrease oldIncrease = this.increase;
this.increase = increase;
propertyChangeSupport.firePropertyChange("increase", oldIncrease, increase);
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
There is JPanel for bind 2 buttons. Here is the biggest problem :/ I'm lack of ideas.
public class ButtonB extends JPanel implements ActionListener{
public ButtonMy b1 = new ButtonMy();
public ButtonMy b2 = new ButtonMy();
public ButtonB (){
init();
}
public final void init(){
setLayout(new GridLayout(1,2));
this.przycisk1.setIncrease(ButtonIncrease.Powieksz);
this.przycisk2.setIncrease(ButtonIncrease.Zmniejsz);
add(b1);
add(b2);
}
}
JFrame where I test this component is very common. Code below shows only function for inc and dec size when separate button is clicked (not in JPanel).
private void buttonMy3MouseClicked(java.awt.event.MouseEvent evt) {
switch(buttonMy3.getIncrease()) {
case Powieksz: setSize(1);
break;
case Zmniejsz: setSize(0);
break;
}
}
I didn't paste full of my code. There some of math functions left which I think they are not needed here (setSize for example).
I'm not sure if i understand the problem correctly but I think under the actionListener class you should have a method called actionPerformed& it will say that if button1 is clicked increase the number, if button2 is clicked decrease the number:
public void actionPerformed( ActionEvent event ) {
if (event.getSource()== b1) // your "increase size" code
if(event.getSource()== b2)// your "decrease size" code
}
button listeners are actually different from mouse listeners; buttons implements ActionListeners and have the actionPerformed method with event variable. you could handle the event by:
getSource() -this method is inherited from java.util.EventObject and returns the OBJECT on which the event initially occurred (the button itself)
or by getActionCommand() -this method is available to action events, or any event that inherits from ActionEvent and returns the command STRING associated with this action.
however mouse listeners implements MouseListener and has a lot of methods depending on what the mouse does (pressed, clicked, released, etc.).

Java GUI adding buttons with a for loop

Hi i am making a lotto gui where the user picks 4 numbers from a selection of 28. The way i am currently doing it is as follows
private void no1InputButtonActionPerformed(java.awt.event.ActionEvent evt) {
numberSelectionList.add("1");
}
private void no2InputButtonActionPerformed(java.awt.event.ActionEvent evt) {
chosenNumDisplayLabel.setText(chosenNumDisplayLabel.getText()+" 2");
}
private void no3InputButtonActionPerformed(java.awt.event.ActionEvent evt) {
chosenNumDisplayLabel.setText(chosenNumDisplayLabel.getText()+" 3");
}
etc up through the 28 numbers.
Is there a way to add the actions to each button through a for loop
as this seems more logical?
Also is there a way to add each number picked into an array?
Create a single Action that can be shared by all buttons. The Action will then simply get the text of the button and then do some processing.
Check out setText method with panel and button. This example will show you how to:
create a single ActionListener to be shared by each button
"append" the text to the text field instead of replacing the text
use Key Bindings so the user can also just type the number
On each button you can set an action command:
button.setActionCommand("1");
And you can get the value after that using your ActionEvent:
evt.getActionEvent();
More complete:
ActionListener listener = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println(e.getActionCommand()+" clicked");
}
};
int howMuchYouWant = 32;
for(int i = 0; i<howMuchYouWant; i++)
{
JButton button = new JButton(""+(i+1));
button.setActionCommand(""+i);
button.addActionListener(listener);
//add to whatever gui you want here
}

How to get the source of multiple JButtons in action listener?

I'm coding a memory matching game using pictures and a JButton array, but I've run into a problem when I try to compare two buttons that were clicked. How do you store the index of/get the index of the second button? All of my buttons in the button array are linked to the same actionListener but e.getSource() will only get the first button clicked, as far as I'm aware. I'd really appreciate some help. (I didn't want to paste in my entire code, because that's a lot, so I'm just putting in parts I think are relevant):
public DisplayMM(ActionListener e)
{
setLayout(new GridLayout(6, 8, 5, 5));
JButton[] cards = new JButton[48]; //JButton board
for(int x = 0; x < 48; x++) //initial setup of board
{
cards[x] = new JButton();
cards[x].addActionListener(e);
cards[x].setHorizontalAlignment(SwingConstants.CENTER);
cards[x].setPreferredSize(new Dimension(75, 95));
}
private class e implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
for(int i = 0; i < 48; i++)
{
if((e.getSource())==(cards[i]))//1st button that was clicked
{
cards[i].setIcon(new ImageIcon(this.getClass().getResource(country[i])));
currentIndex = i;
}
}
//cards[i].compareIcons(currentIndex, secondIndex);
}
}
Also, in my Panel class, I attempted to do something similar, but ended up moving it to the Display class because Panel didn't have access to the button array.
//Panel
public void actionPerformed(ActionEvent e)
{
/*every 2 button clicks it does something and decreases num of tries*/
noMatchTimer = new Timer(1000, this);
noMatchTimer.setRepeats(false);
JButton source = (JButton)e.getSource();
guess1 = source.getText(); //first button clicked
numGuess++; //keeps track of number of buttons clicked
JButton source2 = (JButton)e.getSource();
guess2 = source2.getText();
numGuess++;
if(numGuess == 1)
display.faceUp(cards, array, Integer.parseInt(e.getSource()));
else
display.compareIcons(guess1, guess2);
if(tries != 12 && count == 24)
{
displayWinner();
}
}
You can give your ActionListener class private fields, even if it's an anonymous inner class, and one of those fields can be a reference to the last button pushed. Set it to null after the 2nd button is pushed and you'll always know if the button press is for the first or second button.
e.g.,
class ButtonListener implements ActionListener {
private JButton lastButtonPressed = null;
#Override
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
if (lastButtonPressed == null) {
// then this is the first button
lastButtonPressed = source;
} else {
// this is the 2nd button
if (source == lastButtonPressed) {
// the dufus is pushing the same button -- do nothing
return;
} else {
// compare source and lastButtonPressed to see if same images (icons?)
// if not the same, use a Timer to hold both open for a short period of time
// then close both
lastButtonPressed = null;
}
}
}
}

How to use the resetButton to reset parameters

Im writing a program that deals with creating a house and rearranging the neighbors (similar to game of life)
It is written in Java and it as a Reset button to restart with the current parameters.
The problem is that when i click the resetButton the whole window closes.
You can find the code at the and of the question.
These are other involved fields, so you might be able to understand the code better:
TextField to set the size of the city (number of squares on an edge).
TextFild to set the maximum percentage of neighbors not-like-you that a household will tolerate before they move. I.e., if the number is set to 70, a red house hold with 6 blue neighbors will move; a red household with 5 blue neighbors is ok according to this.
TextField to set a minimum percentage of neighbors not-like-you that a household will tolerate before they move. Make this greater than 0 for a person who LIKES diversity TextField to set the percentage of red households. Note: you can do this with probability. You do not need to have this exact percentage of red households.
TextField to set the percentage of blue households. White will be what is left over. Single step button gives every household one chance to move. You do not need to be careful about that fact that, as you progress through the city, a person early in the move chances may move to a place that later gets a chance (i.e., some households really get two or more turns).
Go button, to start and stop the program from doing steps on its own.
So my questions is how do i let those field and buttons restart with the current parameters ( restart it with what i have originally after playing a few times)
As you can see I added the resetButton to do its job but somehow it is not.
Ok it is like I run the program I have a set of numbers for red and blue as you can see in my, then when I run it it starts with those numbers. And so I keep on changing as i play, and then there is a reset button that lets me reset what I did and should bring back what it originally started with:
public final static int size = 5 and so on
This is my main program
public class Ghetto extends JFrame implements ActionListener, MouseListener,MouseMotionListener
{
protected Grids theGrid;
JButton resetButton;
javax.swing.Timer timer; // generates ticks that drive the animation
public final static int SIZE = 5;
public final static int BLUE = 10;
public final static int RED = 8;
public final static int DIVERSITY_PERCENTAGE = 70;
public static void main(String[] args)
{
new Ghetto();
}
public Ghetto() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
addMouseListener(this);
addMouseMotionListener(this);
setLayout(new FlowLayout());
theGrid = new Grids(SIZE, BLUE, RED, DIVERSITY_PERCENTAGE);
add(theGrid);
resetButton = new JButton("Reset");
add(resetButton);
resetButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resetWithCurrent();
}
});
setSize(new Dimension(550, 600));
setVisible(true);
}
public void resetWithCurrent()
{
//this.dispose();
}
#Override
public void actionPerformed(ActionEvent e)
{
timer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
performStep();
//if (e.getSource() == resetButton )
//{
//resetWithCurrent();
//}
}
});
}
}
Also I added this part
public class Observable{
int state = 0;
int additionalState = 0;
public final void updateState(int increment)
{
doUpdateState(increment);
notifyObservers();
}
private void notifyObservers() {
// TODO Auto-generated method stub
}
public void doUpdateState(int increment)
{
state = state + increment;
}
}
public class ConcreteObservable extends Observable{
public void doUpdateState(int increment){
super.doUpdateState(increment); // the observers are notified
additionalState = additionalState + increment; // the state is changed after the notifiers are updated
}
}
But it didnt make any difference.

How do I make an ImageIcon (or any kind of image really) visible without a JButton?

I'm working on a minesweeper game and I want to make the bomb (or in this case a panda image I created) to show up under the game space when it's pressed. At this point I just want to make it show up under every single space, I know how to do the randomizing of where it shows up after that, the problem is making it show up.
Right now the parts of my code that apply to this topic are in 2 different classes:
1st class
public class MSBoard extends JPanel implements ActionListener
{
int x = 8;
int y = 8;
public GridLayout gl = new GridLayout(x,y,0,0);
public MSBoxes boxarray[][] = new MSBoxes[x][y];
MSBoard()
{
super();
setLayout(gl);
for(int i=0;i<x;i++)
for (int j=0;j<y;j++)
{
boxarray[i][j] = new MSBoxes();
add(boxarray[i][j]);
}
}
public void actionPerformed(ActionEvent ae){}
}
2nd one
public class MSBoxes extends JPanel implements ActionListener
{
public JButton b1;
ImageIcon panda;
MSBoxes()
{
super();
panda = new ImageIcon("panda.gif");
b1 = new JButton();
add(b1);
b1.addActionListener(this);
b1.setVisible(true);
}
public void actionPerformed(ActionEvent ae)
{
if(b1 == ae.getSource())
{
b1.setVisible(false);
}
}
}
use JToggleButton for Minesweeper game
use putClientProperty
use ItemListener for JToggleButton

Categories

Resources