Which button was clicked in Java? - java

I'm working (failing pretty bad so far tbh) on a battleship game for my high school Java programming class. So far I have the game board for both the computer and the player and I have generated the ships for the computer and made sure the player can sink them. Both of the boards have a grid layout, and each of them is assigned to a 2-D array for both the player and the computer and is part of the specific Grid Layout (to be honest I don't really understand a lot of the code because it was supplied by our teacher, so I can't really tell which parts are relevant and which aren't - which is also why I am not posting any of my code).
What I want to do now is let the Player place their ships by letting them pick a starting place by clicking on the board.
inside of a for loop
1: a button in buttonsPlayer is clicked
2: when a button is clicked, the two coordinates are calculated and stored as x, y coordinates
3: a ship is generated with the starting coordinates of x, y
I know how to generate a ship with random x and y starting coordinates as I have done that before. Is there a way to get a button's number in an array after clicking on a button?
(I did read through like 5 other threads on here that seemed to ask the same question, but I don't really get any of the answers)

You could create a class that extends JButton and adds more functionality to a JButton like so:
public class BoardPiece extends JButton{
private int x,y;
//rest of class including getters and setters
}
This will bring all the functionality of JButton along with it and you can add in essentially meta-data about each square.
Then in your event listener you would be able to just call .getX() and .getY() like so:
boardPiece.addActionListener((e)->{
BoardPiece clicked = (BoardPiece)e.getSource();
int x = clicked.getX();
// and so on
});

A JButton has an 'action command' which allows you to put information in it to distinquish it from other buttons.
using
JButton.setActionCommand
JButton.getActionCommand
So if you encode the coordinates of that button in that string, in your actionListener you can
JButton b = (JButton) eventListener.getSource();
and
String cmd = b.getActionCommand();
and then process that cmd string to figure out where on the board you are.

You can give a JButton an ActionCommand, e.g.
JButton button1 = new JButton("Button 1");
button1.setActionCommand("Button1id");`
Then if you implement an ActionListener to listen for the buttonpress, you can write code like
#Override
public void actionPerformed(ActionEvent ae) {
String buttonid = ae.getActionCommand();
}
By checking the value of buttonid, you will know which button was pressed.

Related

The cards do not rotate correctly in my video game made in java (swing)

private class Listener implements ActionListener, MouseListener {
#Override
public void mousePressed(MouseEvent eventClick) {
// Recovery Card from JLabel //
JLabel labelCardClicked = (JLabel)eventClick.getSource();
ImageIcon imageCardClicked = (ImageIcon)labelCardClicked.getIcon();
Card clickedCard = getCardWithFileaname(imageCardClicked.getDescription());
// FLIP //
imageCardClicked = new ImageIcon(clickedCard.getLogo());
imageCardClicked.setDescription(clickedCard.getId());
labelCardClicked.setIcon(imageCardClicked);
sameCardPressed(labelCardClicked, clickedCard);
if(numberCardsClicked == 2) {
Boolean status = controller.sameCard(cardsInGame);
//timer.start();
validateGameUser(status); // Problem here
//To be continued ...
}
My program is the typical card game that when you click on a card, it flips over, and if you make a match, they are removed from the GUI.
Well, when you start the game and click on one card, it flips, but when you click on the second one you don't see that effect. I think it's because there's a one second timeout missing before you get to validateGameUser (status);
That's the only reason I see for it to fail me..., the first card flips and we see it, but the second one doesn't .... when I debug with "System.put.println()" I can see that the card flips, but it's not seen in the GUI as in the first card, that's why I think it reaches validateGameUser (state) very fast and you don't notice the change (since they are removed from the GUI). So I was thinking about a timer .... but I don't know how to link it to my program :/

Swing - How to create a Jbutton that adds e.g Boats to a fleet

For my Project i have to be able to add/remove boats to a fleet.I would like to use a Jbutton for that. I have 10 buttons which 5 are boats and i want to add them to fleet. Code for 1 of 10 jbutton using addActionListener() the thing im trying to do is that if a press a boat button it will print out in a textarea one after another (like a receipt). i have the same code structer for all buttons my second question is-Is there a way of making the code a bit shorter.
button9.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
addBoat.setVisible(true);
button6.setVisible(true);
button7.setVisible(true);
button8.setVisible(true);
button9.setVisible(true);
button10.setVisible(true);
text.setText(john.getText());
text.validate();
okButton.setVisible(true);
}
});
What you did is probably the simplest way that I know of. The only way to make it slightly shorter would be to make an array that includes all of the buttons then make a for loop that does that for you. An example of setting up the array would be:
JButton[] boats = new JButton[5];
And then the for loop would be:
for(int n = 0; n < boats.length; n++){
boats[n].setVisible(true);
}
The only thing I left out is actually adding the JButtons to the array, but this should do it. In the future I would recommend using more helpful names for your buttons to make it easier for others to read your code.

User defined functions-for loops (JAVA)

My question is straight.
I have made a simple app in neatbeans in which when I click a button the x coordinates of the text say a '#' keeps changing by 20.
heres the code:-
int x;
private void wActionPerformed(java.awt.event.ActionEvent evt)
{
x=x+20;
q.setLocation(x, 0);
}
this code simply moves the jlabel ( q ) to the right by 20 coordinates each time i click the jbutton ( w ).
now what i want is that when i click the button only ONCE then the position of the JLabel should keep increasing its x coordinate by 20 untill it has reached a specific x coordinate say 200.
i tried using for loops :-
private void wActionPerformed(java.awt.event.ActionEvent evt)
{
for(x=0;x<201;x=x+20)
{
q.setlocation(x,0);
}
}
but with this when I click the button, the jlabel directly moves to 200 x coordinate without stopping after every 20 coordinates...please help..
Regards,
Slinger
The problem with the above is that Swing is calling your incrementer and only performing a refresh once your incrementing function has completed. Instead you need to start up a separate thread to perform this animation and let Swing update after each increment.
Check out SwingUtilities.invokeLater() and the SwingWorker class. Here's a tutorial on SwingWorker.

Java Swing mouseDragged callback speed

I have a question regarding the callback speed of the mouseDragged message of the MouseMotionListener in Java Swing. This post is sort of related but it's not entirely the same so I started a question of my own.
I'm making a small in-house application with no eye on commercial distribution that is basically a digitalized TCG (Trading Card Game) emulator. For any of you familiar with MtG (Magic the Gathering), you might've heard from such a similar program. I'm trying to create something that looks sort of like this, but less fancy.
My GUI consists of a JFrame with menu and then some panels containing various buttons and labels, but I'll only go over the relevent parts to explain my problem.
In essence, I'm using a vertical split JSplitPane with a JPanel on the left, with in that a JScrollPane with a JList in it, which represents at any time the cards in your hand that you can play. On the right side of the split, I have a JLayeredPane with a background image in the DEFAULT_LAYER (subclass of JPanel that overrides the draw function to add an image) and, on various layers above the PALETTE_LAYER, I display the cards that are in play (gathered in an ArrayList) by means of custom CardPanels (another subclass of JPanel that illustrates a card). The entire JLayeredPane is thus a representation of the table in front of you with all the cards you've already played.
I first started by adding a MouseListener and a MouseMotionListener to the JLayeredPane to pick up events, allowing me to register a mouse press, check if this was above a card, then use the mouse dragged event to move the card around and finally mouse release to place it back . This all works perfectly fine and if I add logging information I can see the mouseDragged callback function is called often, allowing for a visually fast dragging motion without lag.
Today I decided to add functionality to allow the user to drag a card from his hand to the "table" (instead of double clicking on the card in the JList), so I added the appropriate listeners to the JList along with filling in some functions like MousePressed and MouseReleased. On a mouse press, I check what card from the list was clicked, I lock the list, create a custom CardPanel (but don't add it anywhere yet, I just allocate and initiate it!) and set a flag. In mouse dragged, I check if this flag is set. If it is, I check where the cursor is. If it is anywhere above the JLayeredPane, I add the CardPanel to the DRAG_LAYER and set another flag. If this second flag is set in successive calls to mouse dragged, I don't add the panel again but I just change the location. This functionality is practically the same as the one in my previous mouse dragged callback. On mouse release, I unlock the list and add the CardPanel on the correct layer in the JLayeredPane.
Everything is working as intended so I'm pretty sure my code is okay, but there is just one slight issue:
When dragging a card from the list to the layered pane (instead of from the layered pane to the layered pane), I notice the mouseDragged callback is called at a pretty low frequency by the JList (approx 10 times per second), introducing some visually disturbing lag (compared to approx 30 times per second in the first case of dragging).
I'm going to add some code snippets as to clarify my problem but I'm afraid adding all the code to allow you to run it yourself would be serious overkill.
The main question in this post is: does anybody know why the mouseDragged is called faster by one MouseMotionListener than by another MouseMotionListener? The listener to the JLayeredPane component makes fast successive calls, the listener to the JList calls significantly slower.
Note: I'm developing in Netbeans and I'm using the built-in graphical Swing Interface Builder. I'm using a JFrame form as my main class.
public class MyFrame extends JFrame{
...
protected JLayeredPane layeredPane;
protected JList cardsInHandList;
...
...
protected ArrayList<String> cardsInHand;
...
private void attachListeners(){
layeredPane.addMouseListener(new MouseAdapter(){
public void MousePressed(MouseEvent e){
// set a flag, start a drag
}
public void MouseReleased(MouseEvent e){
// unset a flag, stop a drag
}
});
layeredPane.addMouseMotionListener(new MouseMotionAdapter(){
public void MouseDragged(MouseEvent e){
// drag the card around
// gets called a lot!
// actual code:
if (e.getButton() == MouseEvent.BUTTON1) {
if (!dragging) return; // the flag
int x = e.getX() - 10;
int y = e.getY() - 10;
// snap to grid
x /= GRIDX;
x *= GRIDX;
y /= GRIDY;
y *= GRIDY;
// redraw the card at its new location
draggedCard.setLocation(x, y);
}
}
});
cardsInHandList.addMouseListener(new MouseAdapter(){
public void MousePressed(MouseEvent e){
// set a flag, start a drag
}
public void MouseReleased(MouseEvent e){
// unset a flag, stop a drag
}
});
cardsInHandList.addMouseMotionListener(new MouseMotionAdapter(){
public void MouseDragged(MouseEvent evt){
// check cursor location, drag if within bounds of layeredPane
// gets called a whole lot less!! _Why?_
// actual code:
if (!draggingFromHand) return; // the flag
// check location of cursor with own method (contains() didn't work for me)
if (isCursorAtPointAboveLayeredPane(evt.getLocationOnScreen())) {
// calculate where and snap to grid
int x = (int) (evt.getLocationOnScreen().getX() - layeredPane.getLocationOnScreen().getX())-10;
int y = (int) (evt.getLocationOnScreen().getY() - layeredPane.getLocationOnScreen().getY())-10;
// snap to grid
x /= GRIDX;
x *= GRIDX;
y /= GRIDY;
y *= GRIDY;
if(!draggingFromHandCardPanelAdded){
layeredPane.add(draggingFromHandCardPanel, JLayeredPane.DRAG_LAYER);
draggingFromHandCardPanelAdded = true;
} else {
draggingFromHandCardPanel.setLocation(x,y);
}
}
}
});
}
I'll try to build a short runnable example reproducing the problem and then attach the code somewhere but right now I got to skoot.
Thanks in advance
PS: I am aware that there is another way to drag in Java, involving TransferHandlers and all that but it just seems like too much hassle and it isn't an actual answer to my question of how come the one callback seems to be called more than the other, so please don't tell me to use that instead.
Once you drag outside the list, Java start generating synthetic mouse events for the list, which might be the cause. See the javadoc for JComponent#setAutoscrolls(boolean).
You might get better results using a global event listener, see
http://tips4java.wordpress.com/2009/08/30/global-event-listeners/

Hold down a key while clicking on a JTextField in Java, how to get the key?

I have a JTextField represents a day in a week, such as "Friday", when I click on it, I want to have a choice such as "1st of month, 3rd of month or last of month", so I came up with two options :
<1> Hold down a number or letter, let's say "2" or "L", then click on "Friday" means 2nd (or last) Friday of the month, in this case, how to get the number while mouse clicks on the JTextField ?
<2> Right mouse click on the "Friday" JTextField, drop down a menu, with either buttons or checkboxes that let me choose, then close the menu and get the value.
My code look like this so far :
private final JTextField[] dayHeadings=new JTextField[]{new JTextField("Su"),
new JTextField("Mo"),
new JTextField("Tu"),
new JTextField("We"),
new JTextField("Th"),
new JTextField("Fr"),
new JTextField("Sa")};
......
for (int ii=0; ii < dayHeadings.length; ii++)
{
dayHeadings[ii].setEditable(false);
dayHeadings[ii].setFocusable(false);
dayHeadings[ii].addMouseListener(new MouseAdapter() { public void mouseClicked(final MouseEvent evt) { onHeadingClicked(evt); } });
add(dayHeadings[ii],new AbsoluteConstraints(x,38,X_Cell_Size+1,Y_Cell_Size+1));
}
......
void onHeadingClicked(final java.awt.event.MouseEvent evt)
{
final javax.swing.JTextField fld=(javax.swing.JTextField) evt.getSource();
...
}
How to do either of the above, are they doable in Java ?
getModifiers is actually that what I needed. a sample for the modifiers can be found
here
Option 1:
There is no way to do this in one step. You would need to add a KeyListner to track whenever a key is pressed and then save the character value. Then you would need to add a MouseListener to listener for mousePressed events. When the mousePressed event fires you would need to to check which character is saved and then do your processing. Therefore your listener would to implement both the KeyListener and MouseListener interfaces.
Option 2:
You need to add a mouse listener and listen for a right mouse click, then display a popup menu.
I think option 2 is more intuitive and more easily done. Its always easier to work with one hand then be forced to use two hands.
Another, lazier way to do it would be using getModifiers() on the mouseclick event. It shows which modifier keys (ctrl, alt, shift, etc), if any, were pressed during the mouse click. Using these buttons isn't as intuitive as a drop down menu or numbers in my opinion, but could work.
Read more here

Categories