Detect which button was clicked in a 2D array Java - java

In our code we have a 10 by 10 button array.
We made the 10 by 10 array using a nested for loop, and we have no issue creating the buttons.
Also, we have it so that when a button a is clicked it displays "Button Clicked". But how can we identify which button was clicked?
We're using actionListeners and actionPerformed methods.

You can call the getSource() method on the event.
Or you can use Action classes in your buttons and create a new instance of each when you build the buttons.

Put all the buttons in a list (easily accomplished in the inner loop), make the list available to the ActionListener (eg. as a property of the outer class; I do not know how your numerous team arranged the listeners, so I cannot provide any details). Then call:
int buttonIndex = listWithButtons.indexOf(event.getSource())
If one of you wants to know the exact coordinates of the button, they can be calculated by the formulas:
int row = buttonIndex / 10;
int col = buttonIndex % 10;

I'm assuming this is a JButton. You can use setActionCommand("command" + row + "-" + column). Then in the listener just say getActionCommand() to see which button was clicked.

Two simples solutions, but probably not the best ones :
The button class implementing its own listener.
You can also just test each button to see if it equals the action.getSource() object.
Or simply cast (ButtonClass) to the getSource() to be able to use the retrieved button.

You can use getActionCommand just like this:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestButtons extends JPanel {
private static final long serialVersionUID = 1L;
public TestButtons() {
JButton btn1 = new JButton("Btn1");
btn1.addActionListener(new ButtonListener());
add(btn1);
JButton btn2 = new JButton("Btn2");
btn2.addActionListener(new ButtonListener());
add(btn2);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new TestButtons());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
class ButtonListener implements ActionListener {
ButtonListener() {
}
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand()+ " has been clicked");
}
}

We ended up using a nested for loop inside of actionPerformed that ran through the 2d array and called the action methods from there. It probably isn't the best solution, and it's probably best to use a different technique, but it seems to work just fine.
Though there are some really nice ideas in here, thank you guys!

Related

How to update components listening a button in java

I am a bit sorry to ask this question, since it seems to be a bit obvious, but I can't find my solution alone.
I am coding a little app in Java, and I encounter some issues "redrawing" my swing components. Basically, I want my JFrame to update when an event occurs. I managed to reproduced the issue in the code below. This code is supposed to display two buttons (which it does), and replace them with a third button when you click on the first button (which it doesn't).
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame implements ActionListener {
private JButton button = new JButton("Button 1");
private JButton button2 = new JButton("Button 2");
private JButton button3 = new JButton("Button 3");
private JPanel buttons = new JPanel();
public void init() {
this.setVisible(true);
this.setSize(500,500);
buttons.add(button);
buttons.add(button2);
this.add(buttons);
this.button.addActionListener(this);
}
public void update() {
this.removeAll();
buttons.add(button3);
this.revalidate();
}
public static void main(String[] args) {
Example ex = new Example();
ex.init();
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button) {
update();
}
}
}
I am pretty sure that I am doing something wrong in the update() method. I actually have a lot of trouble to understand how works removeAll(), revalidate(), repaint() etc, and I guess that is the problem. I tried to call the same methods on the buttons panel, it almost worked but I still have a graphic bug, and I would like to do it for all the container. I also tried to call these methods on this.getContentPane(), but it doesn't work.
Can anyone try to help me with it?
You're removing all components from this (which in this case is the JFrame (as you're extending it, which isn't needed, and instead you should create an instance from it rather than inherit from it, as you're not changing the behavior of the JFrame so it's better to just create an instance of it). See: Extends JFrame vs. creating it inside the program
In this case you're adding your components in this way:
JFrame > buttons (JPanel) > JButtons
And you're trying to remove
JFrame > everything
That includes the contentPane, instead you should call.
buttons.removeAll()
Inside the update() method.
And also call this.repaint() so your update() method should become:
public void update() {
buttons.removeAll();
buttons.add(button3);
this.revalidate();
this.repaint();
}
Or the best approach is to use CardLayout as recommended by #AndrewThompson in the comment below. This way you don't have to handle removing / repainting for each component, as CardLayout will do it for you. For example
this works,
public void update() {
buttons.remove(button);
buttons.remove(button2);
buttons.add(button3);
this.revalidate();
this.repaint();
}

Adding a action listener in java for a counter

I am a fairly new user with programming in Java with about a week and a bit experience, as of before I have been using python for about 3 years but thought to give java a try.
I have been trying to develop my skills by creating small projects and applications and am now creating a small GUI counter.
I have achieved creating the GUI with 2 buttons and a label and have tested the maths behind the application but I am struggling to work out how the ActionListener works as it feels a lot different to python when making a button have a action.
This is My Code;
package gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.*;
public class GUI{
//This creates a frame or panel to contain things
public static void main(String[] args) {
//Maths To The Counter
int Counter = 0;
System.out.println(Counter);
Counter =+ 1;
System.out.println(Counter);
//Creating The Frame
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel);
//Creating The Label
JLabel label3 = new JLabel("Counter: ");
panel.add(label3);
//Button Which should have a funtion to add and display the number
JButton button = new JButton("Click Here.");
panel.add(button);
//Button to reset the counter
JButton buttonReset = new JButton("Reset Counter.");
panel.add(buttonReset);
//Set Size Of Window
frame.setSize(new Dimension(500, 400));
//Set Starting Position to centre
frame.setLocationRelativeTo(null);
//Setting a default close action
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set Title
frame.setTitle("Counter");
//Disable Resize
frame.setResizable(false);
//Setting if its visible
frame.setVisible(true);
//Fits frame to fit everything
frame.pack();
}
}
enter code here
I know that in python a action is in a function so that has been my logic to this problem however I have seen that I need to use the actionlistener instead and I am struggling to get my head around it.
If Someone could show me how this type of action should be implemented it would be great help, I have watch some youtube videos and done a bit of research but im still struggling to understand in my situation how to do it.
For any confussion im sorry, overall my question is how do I add a action to a button in my program that can implement my maths at the start.
As well any feedback on the structure of my code would be welcomed as I am just starting in java and I do know poor structure can lead to mistakes.
This code should work:
Basically, in the main method I am creating an instance of the class and calling a method to create the gui.
I also created an instance variable as the counter, otherwise you won't be able to update the variable in your action listener.
public class Gui {
private int counter;
// This creates a frame or panel to contain things
public static void main(String[] args) {
Gui gui = new Gui();
gui.create();
}
private void create() {
// Creating The Frame
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel);
// Creating The Label
JLabel label3 = new JLabel("Counter: ");
panel.add(label3);
// Button Which should have a funtion to add and display the number
JButton button = new JButton("Click Here.");
panel.add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(counter++);
}
});
// Button to reset the counter
JButton buttonReset = new JButton("Reset Counter.");
panel.add(buttonReset);
buttonReset.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter = 0;
}
});
// Set Size Of Window
frame.setSize(new Dimension(500, 400));
// Set Starting Position to centre
frame.setLocationRelativeTo(null);
// Setting a default close action
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set Title
frame.setTitle("Counter");
// Disable Resize
frame.setResizable(false);
// Setting if its visible
frame.setVisible(true);
// Fits frame to fit everything
}
}
With Lambda expressions, you can simplify your action listeners as follows:
button.addActionListener(a -> System.out.println(counter++));
buttonReset.addActionListener(a -> counter = 0);
If you want to write more than 1 statement, then you can just put your code in curly brackets:
button.addActionListener(a -> {
System.out.println(counter++);
System.out.println("doing more stuff...");
});
JButton has a function called addActionListener. You can pass on an action listener by doing this:
button.addActionListener(() -> {
// Do some logic here
});
Here, I use a lambda expression as an action listener. Within the lambda expression you can place whatever logic you want to have.
Also note that you can add multiple different action listeners to the same button. In a nutshell, the way the JButton interacts with the ActionListeners is based on the observer-pattern.
Imagine this: When the JButton is pressed, it will notify all of it's observers saying "Hey, I have been pressed". Each observer can then independently decide what to do. In case of the JButton, all observers are ActionListeners. If you add multiple ActionListeners then the JButton will notify all of them, and as a result all of their actionPerformed(ActionEvent e) functions are executed. In the example above, I used a lambda expression which then by java is interpreted as an ActionListener.
Other ways to achieve the exact same functionality are:
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Do some logic here
}
});
In the example above, you use an anonymous class as an actionlistener.
public class MyClass {
public MyClass() {
JButton button = new JButton("press me");
button.addActionListener(new MyActionListener());
}
private class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Do some logic here
}
}
}
In the example above, an inner class is used.
In a nutshell, there is a ton of ways you can make your button have functionality. Above are just a few examples of how to do so.
Does this clarify it a bit more, or do you have some remaining questions?

AS3 - Button Click + Number

What I'm trying to do is create a very basic button click game much like "AdVenture Capitalist" and several other casual games like it. Nothing quite as fancy. I'm using FlashDevelop (AS3) and I'm trying to figure out how to create a button then every time that button is pressed it adds +1 to my main value represented on screen.
I'd also like to figure out how to make a button that would automate the clicking process.
If anyone could show me how, or direct me to a specific page that would help me out I would be very thankful.
I'm also not sure if Actionscript is the best language to write this in. If you have a recommendation that I can use FlashDevelop with I would appreciate the tip!
Thank you!
I have idea about the how this operation will be performed in java. For example creating buttons and labels. As long as you need to combine java and flash this link is useful for starters. If you need only java the following snippet will be useful. Also learn java swing from JavaDocs for GUI purpose
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonClick
{
int counter = 0;
public ButtonClick()
{
JFrame frame = new JFrame("Title");
JButton btn = new JButton("Click me");
JLabel clicks = new JLabel("");
frame.setSize(400,400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
counter++;
clicks.setText("Number of clicks till now :"+Integer.toString(counter));
frame.repaint();
}
});
frame.add(btn);
frame.add(clicks);
frame.setVisible(true);
}
public static void main(String []args)
{
ButtonClick c = new ButtonClick();
}
}

GUI - How do I switch between panels or frames while saving user input

So I have a layout made with buttons,textfields, and labels. A user is supposed to put input into the textfields. When he hits a button, I want it so that the input is cleared and a new "page" is shown with the layout i have made. The user can input as much information into new "pages" as he wants until he hits an "finished" button. In short, I want to switch between panels or frames (i dont know which, probably panels??). Now, I was thinking of using card layout to do this but since i'm reading user input it wouldn't really make sense since cardlayout is made based on a predetermined amount of panels and what will be in the panels. Since I won't know when the user is "finished", I won't know how many panels to use.
Anyways, I'm just a beginner with GUI so any help would be great!
Now, I was thinking of using card layout to do this but since i'm
reading user input it wouldn't really make sense since cardlayout is
made based on a predetermined amount of panels and what will be in the
panels. Since I won't know when the user is "finished", I won't know
how many panels to use.
You can dinamically add components to CardLayout on next button's click. If all the pages have the same structure you can have a class for those pages and add a new one every time next button is pressed. When finish button is pressed do something with all those pages iterating over the panel (with CardLayout) components. Take a look to Container.getComponents() method. You don't even need to keep any kind of array nor list because the container already do so.
Example
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Demo {
private void createAndShowGUI() {
final JPanel cardPanel = new JPanel(new CardLayout());
cardPanel.add(new Page(), "1");
final JButton nextButton = new JButton("Next");
nextButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardPanel.add(new Page(), String.valueOf(cardPanel.getComponentCount() + 1));
CardLayout layout = (CardLayout)cardPanel.getLayout();
layout.next(cardPanel);
}
});
final JButton finishButton = new JButton("Finish");
finishButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
nextButton.setEnabled(false);
for(Component comp : cardPanel.getComponents()) {
if(comp instanceof Page) {
Page page = (Page)comp;
page.printData();
}
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(nextButton);
buttonsPanel.add(finishButton);
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(cardPanel, BorderLayout.CENTER);
frame.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class Page extends JPanel {
final private JTextField data;
public Page() {
super();
add(new JLabel("Please add some info:"));
data = new JTextField(20);
add(data);
}
public void printData() {
System.out.println(data.getText());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
As far as I understand from your description you do not need multiple panels. I am assuming that you have some sort of object hierarchy for your model layer. So, let's say you use those input values to create AnObject objects.
You can create an ArrayList<AnObject> in your top class. And as user inputs and clicks done you just create one more AnObject with given input and add it to the ArrayList you defined in top class.
BTW, you can also define ArrayList whereever it is reachable. But you must think carefully, to keep your data persistent. If the object of the class that you defined ArrayList is "gone", your data is also "gone". I think this should be clear enough.
The next step is just trivially clearing out those input fields.
This is the most straightforward way, it may not be the smartest way to do that depending on your use case. But it would give you an idea for what to look and learn for.

Button Counter-Java

I need help making a program that has 2 button. A message appears “I was clicked n time!” whenever the button is clicked. Each button should have a separate click count.
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class ButtonViewer
{
private static final int FRAME_WIDTH = 400;
private static final int FRAME_HEIGHT = 360;
public static void main(String[] args)
{
int counter1 = 0;
int counter2 = 0;
JFrame frame = new JFrame();
JButton button = new JButton("Click me!");
frame.add(button);
JFrame frame2 = new JFrame();
JButton button2 = new JButton("Click me too!");
frame2.add(button2);
ActionListener listener = new ClickListener();
button.addActionListener(listener);
button2.addActionListener(listener);
counter1++;
counter2++;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame2.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.setVisible(true);
}
}
To start your going to need to actually add a ClickListener, by actually writing another method below like:
private class listener1 implements ActionListener{
public void actionPerformed(ActionEvent e){
counter1++;
}
}
you have 2 of these classes in this case... one per button.
The second listener would just increment the other counter, when the button is pressed.
A simple solution would be to implement the ActionListener inline. Just do:
button2.addActionListener( new ActionListener(){
...
});
When implementing the actionperfomed method in there, you can easily change the text of button2.
You don't have a call back for the action listener, therefore when you click on the button, the listen knows something is happening but don't have any instruction on what to do. Like #KingWilliam mention, this looks like homework, so looking into action listener call back should be enough to get your gears moving.
the listener is an interface, so in the implementation class, you need to make sure that the actionPerformed() method is implemented. you just need to detect the resource of the 'click' event, if it is coming from button increase the button's counter, and to the same to the button2,.
intialize two variables for the count, say count1,count2. For Button 1 register anonymous class as an event listener like this:
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
count1++;
new CustomMessage(count1);
}
});
where CustomMessage should be like:
class CustomMessage extends javax.swing.JDialog{
public CustomMessage( int counter){
//...
}
}
make sure to incorporate 'counter' in your message.
Follow similarly for button2. Hope this works for you!
Best of Luck.

Categories