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?
Related
I posted a question earlier about this but the solution never worked and now it's under different circumstances. I'm making a "penny pitch" program, that, when the "confirm" button is pressed, a randomized number will dictate which spot on the board(the board is fill with image icons) the "penny" will fall, and in the process it removes the image icon that use to occupant the chosen space.
I set up a GridBagLayout to constrain each icon down, and my button has no problem removing the chosen spot, but it can not find a way for it to add a new icon in it's place. It just gets adds onto the end of the JPanel.
Heres my coding for the button:
private class AddListener implements ActionListener {
public void actionPerformed(ActionEvent a){
if (a.getSource()== confirm) {
if (numberToss >0){
thrown = pitch.nextInt(25) + 1;
System.out.println(thrown);
//kol is an array to check for repeated numbers in randomization
if (kol.contains(thrown)==false){
input.remove(spot.get(thrown));
//spot is a map to set icons down with a association with number
spot.put(thrown, bSet);
input.add((spot.put(thrown, bSet)));
repaint();
kol.add(thrown);
}
else {
JOptionPane.showMessageDialog(null, "Your toss landed onto an occupied spot; you receive no points");
}
numberToss--;
}
else{
JOptionPane.showMessageDialog(null, "Out of tosses.");
}
}
}
Anyone happen to know how to replace the new icon (bSet) with the former? Thanks in advance!
I have a group of loop generated buttons made with this code
this.panelCuerpo.setLayout(new GridLayout(4,5));
for(int i = 1; i<=20; i++){
final JToggleButton b = new JToggleButton(new ImageIcon("/images/available.png"));
panelCuerpo.add(b);
b.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Images/available1.png")));
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt){
if(b.isSelected()){
b.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Images/busy1.png")));
cantidadBoletas++;
}else{
b.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Images/available1.png")));
cantidadBoletas--;
}
System.out.println(cantidadBoletas);
}
});
}
The problem here is that I can't use setText() to compare later cause there's no property to hide that text. How can I compare it later?
PS. Each button has a consecutive number, it's easy to assign that number. The real problem lies in where to put it.
You could:
Use the Action API, which lets you trigger the selected state of the associated button. This allows you to de-couple the button from the underlying "action" it should take. Take a look at How to Use ActionsHow to Use Actions for more details
Use the actionCommand property of the JButton. This allows you to have some kind of "identifier" associated with the button which is independent of the text
Use an array or List to maintain a reference to the buttons
You can maintain a List<JToggleButton> of JToggleButton and fetch element later by the index. Apart from that instead of adding ActionListener in loop you can implement ActionListener which can be used for all buttons and you just need to write b.addActionListener(this); in loop.
NOTE : better to start from i = 0 instead of 1
this is a problem that I've been really struggling with
I need to create a game for some University coursework. The game is basically a 4x4 grid. When i click a button, the player should move randomly within 1 square of it's location.
There's enemy spaceships that are generated randomly over the grid, and if the player lands on the spaceship, it destroys it. if there's two enemy ships on the same sqaure and the player lands on that square, the player is destroyed.
I've created a GIU using gridlayout and the button that I need to move the player, but I'm having problems trying to figure out how to actually use the grid. I've created an element class to create objects for the grid (ie, a list of enemy ships), but I don't know how to use this class with my gridlayout. I know I also have to redraw the grid after each move to reflect the changes, but I don't know if I would need to create a custom redraw method for this.
Any push in the correct direction so I can get my program actually doing something would be really helpful.
Some time ago I created a card game that also operated based on a GridLayout. Below is some of the code that was used to drive major events:
CardPanel extends JPanel {
public CardPanel() {
setLayout(gridLayout);
placeCards(N);
chatBoxText = new JTextArea(5, 30);
}
public void placeCards(int numCards) {
for (int i = 0; i < numCards; i++) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.add(new GraphicCard(card, jLabel));
add(jLabel);
jLabel.addMouseListener(this);
}
if (GameLogic.noSetsOnBoard(cardSet)) {
gridLayout.setRows(gridLayout.getRows() + 1);
placeCards(3);
}
}
public void updateCard(Integer location) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.set(location, new GraphicCard(card, jLabel));
jLabel.addMouseListener(this);
}
}
The CardPanel here is an object that represents the GridLayout (you see the constructor) as well as some of those helper methods.
Further on, on particular actions, I have the following code:
cardPanel.removeAll();
// Some other logic here
for (GraphicCard card: cardSet) {
cardPanel.add(card.getJLabel());
}
cardPanel.revalidate();
cardPanel.repaint();
In short, yes, it is custom, but it is not difficult. There are better ways to do it than the above such that you do not need to empty the entire panel in order to refresh it, the logic I have omitted above merited this particular solution.
The approach I used kept track of a CardPanel object which was an abstraction that contained not only the information that each box represented (in my case a card with some values), but also the graphic element to be rendered.
This was some time ago, so I don't recall the exact details but hopefully this is helpful.
I am working on a lab, it's a connect four game. I'm having trouble specifically with basic concepts like how classes communicate with each other, how to use private instance variables, how to use an ArrayList, how to compare JLabels or set them as something comparable...
To give a brief breakdown I have four classes GUI, Game, Player, Name
I can create the GUI by using two four loops, the game is a grid with 7 columns of 6 pieces. The pieces are images,
JLabel Piece = new JLabel("images/blank.png");
for example to denote an empty spot.
The GUI is based on a JFrame, single content pane and four panels, one for a header which indicates who is playing and who won, another for the 7 buttons accompanying the 7 rows, the grid itself of the possible places to be played and then a button panel which gives you the option to replay.
I'm lacking in a lot of concepts. For instance, the replay button shouldn't appear until the game has ended.
I don't understand how to use an ArrayList. I tried to use
ArrayList<ArrayList<JLabel>> myList = new ArrayList<ArrayList<JLabel>>();
So when I create the GUI by running two for loops like so
For ( c = 0 ; c<8 ; c++) {
ArrayList<JLabel> column = new ArrayList<JLabel>();
For ( r = 0 ; r<7 ; r++) {
ArrayList<JLabel> row = new ArrayList<JLabel>();
JLabel empty = new JLabel("images/blank.png");
row.add(empty);
}
column.add(row);
}
Even this small step I've already got confused.
I know the two for loops above are not correct specifically the ArrayList.
I don't know how to create the arraylist and then use them.
using something like
column.get().get();
myList.get().get();
to get a specific piece.
I don't know how to pass that to an argument so that for example if I push on button 7 for column 7, and no pieces have been played yet, I can start from the lowest area column 7 row 6 and update that to a played piece, red or yellow for the appropriate player.
This is vague and I doubt I'll get anywhere but I am desperate for help. There isn't much time available from the TA's / Teacher and I believe I am lacking significantly to be able to finish this project.
I understand how it works/what I have to do in words but in terms of applying Java code...
I'd appreciate any help.
OK first off you should use an array of Enums. ArrayLists are intended for lots of items and that can have rapidly changing numbers. Arrays are intended to house data in a grid of some sorts. Since you are using a static board, use arrays! They are also much less memory-intensive. Example:
//Note you should use [column][row] as that is common practice.
States[][] grid = new States[7][6];
//And initialize it:
for(int i = 0; i < grid.length; i++)
for(int o = 0; o < grid[i].length; o++)
grid[i][o] = EMPTY_JLABEL;
Then declare an enum (this is a new class) (NOTE: replace FULL_PLAYER_ONE_JLABEL and FULL_PLAYER_TWO_JLABEL with the JLabels that have the image for each.):
public enum States {
FULL_PLAYER_ONE(FULL_PLAYER_ONE_JLABEL), FULL_PLAYER_TWO(FULL_PLAYER_TWO_JLABEL), EMPTY(EMPTY_JLABEL);
//The image of the appropriate state.
private JLabel label;
//Enum constructors must be private
private States(JLabel label) {
this.label = label;
}
public JLabel getLabel() {
return label;
}
}
In your GUI, have a JButton that is only added to the frame when the game is over. Also add a button to indicate when each column has been clicked by the player.
JButton button = new JButton();
//Initialize JButton and add to frame...
//Anytime before the frame is set to visible:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
/* Perform tests for for what should happen.
For example test whose turn it is then call a method to add a piece to that column. Then call a checker to see if someone has won. If so, display the replay button, otherwise do nothing (allow other player to move).
*/
}
}
HI all,
I'm trying to write a simple star rating component. I'm fairly new to the Java language and I'm not sure if what i want to accomplish can even be done in Java. Is it possible for me to add a JLabel inside an array of JLabel, and each JLabel in the array will have a mouse event listener. Now is it possible to set it up so that when the mouse event fires on say Label[3] that i can get the index value of it?
Here is how I built my Panel
public Rating(Integer max,int size) {
JLabel position = new JLabel[max];
this.setLayout(new FlowLayout());
for(int i=0; i != max;i++){
position[i]=new JLabel(icons.getIcon("star-empty", size));
position[i].setOpaque(true);
position[i].addMouseListener(this);
add(position[i]);
}
}
#Override
public void mouseEntered(MouseEvent e) {
JLabel a= (JLabel) e.getComponent();
//****Have some code in here to tell me where in the position array the event came from????***
int index = ?????
}
Thoughts/Idea/Suggestions please.
Note I thought of using buttons, but it looks messy and would love to find a way with ImageIcons.
THanks.
Instead of using the same listener for each label like you did:
position[i].addMouseListener(this);
...you can create a special listener class that takes the index number, and allows you to find it later:
position[i].addMouseListener(new RatingMouseListener(i));
Each label will have a separate instance of the listener with a different index value. The code for the inner class would look like something like this:
private class RatingMouseListener extends MouseAdapter {
private final int index;
public RatingMouseListener(int index) {
this.index = index;
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("Mouse entered for rating " + index);
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("Mouse exited for rating " + index);
}
}
Then, you just override any method in MouseAdapter.
Also, like other people said, you might want to use JButtons instead of JLabels because they have better support for action events. You can still give them icons.
You could name each JLabel according to its index using its setName method, then use the MouseEvent's getComponent method to get the originating JLabel back, use getName on it and there's your index. That would be one way, but would involve storing the index information in two places (implicitly in its placement in the array, and explicitly as the label's name), so it's pretty much begging for inconsistency to arise.
You could also search through the array for the JLabel reference you get from getComponent, but that's not so great either, especially for large arrays.
The way I usually do it is:
int i;
for (i = 0; i <max; i++)
if (position[i] == e.getcomponent())
break;
now position[i] is the label you are looking for.
Just know that JButtons can look any way you'd like. They can have ImageIcons and don't even have to look like buttons.
Why is the index important? You know how to get the component, so just loop through the array to get the index.
Note I thought of using buttons, but it looks messy and would love to find a way with ImageIcons.
How does using a button solve the problem of determining the index? However, I also agree using a button is better than a label and then you would use an ActionListener instead of a MouseListener. You can make the button look like a label by using:
button.setBorderPainted( false );
Now if you use an ActionListener you can use the setActionCommand(...) method to store the index value of the button. Then in the event you use the getActionCommand(...) method.