Suppose I have an array of buttons
private JButton[] myButtons = new JButton[5];
for (int i=0; i<5; i++)
{
myButtons[i] = new JButton(Integer.toString(i));
myButtons[i].setSize(50, 50);
panel.add(myButtons[i]);
}
How can I add a listener to these buttons so that when I click on one of them, I know at which array position index it is at?
You kind of don't care, start by adding an ActionListener to the buttons
myButtons[i].addActionListener(this); // Or some other ActionListener
In the actionPeformed method, you can look up which button it is using the ActionEvent#getSource
#Override
public void actionPerformed(ActionEvent evt) {
for (JButton btn : myButtons) {
if (btn.equals(evt.getSource()) {
// Do what ever you need
break;
}
}
}
You can also use the actionCommand property of the JButton
for (int i=0; i<5; i++)
{
myButtons[i] = new JButton(Integer.toString(i));
myButtons[i].setActionCommand("button " + i);
myButtons[i].addActionListener(this);
panel.add(myButtons[i]);
}
And when actionPeformed is called, use ActionEvent#getActionCommand to figure out which button was pressed.
A better idea might be to create a dedicated ActionListener for each button...
public class ButtonActionHandler implements ActionListener {
private final JButton button;
public ButtonActionHandler(JButton button) {
this.button = button;
}
public void actionPerformed(ActionEvent evt) {
// Do what ever you need to do with the button...
}
}
for (int i=0; i<5; i++)
{
myButtons[i] = new JButton(Integer.toString(i));
myButtons[i].addActionListener(new ButtonActionHandler(myButtons[i]));
panel.add(myButtons[i]);
}
Another idea would be to make use of the Action API which would allow you to define a self contained entity which was capable of configuring the button and handling the associated action event by itself. See How to Use Actions for more details
But which you might use will come down to why you need to identify the buttons in the first place.
You can add listener in loop, like below if you implement ActionListener interface with class. For example,
class TestGUI extends JPanel implements ActionListener{
public TestGUI(){
for(int i=0; i< 5; i++){
....
myButtons[i].addActionListener(this);
}
}
or, if you have separate Listener class or method.
myButtons[i].addActionListener(new MyListener());
Than at actionPerformed method you can check with button is clicked,
public void actionPerformed(ActionEvent e){
if("0".equals(e.getActionCommand())){
System.out.println("First button is clicked");
}
... so on
}
Related
I am currently trying to set up a Tic Tac Toe GUI grid with 3x3 buttons, which change the button icon to a nought or cross whenever pressed.
I have set up an array of JButtons and have added a listener to check whenever the button is pressed.
My problem is getting access to the Button object inside the array, I have had to add a parameter to my custom listener constructor to save the button object reference for when I want to change it. It works as is, but doesn't feel very elegant. Is there a way to find the correct JButton object in buttons while inside actionPerformed, or is there a better way to do this altogether?
Thanks in advance
class BigPanel
{
public JPanel bigPanel= new JPanel(new GridLayout(3,3));
public JButton[][] buttons = new JButton[3][3];
public BigPanel()
{
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
{
buttons[i][j] = new JButton();
buttons[i][j].setPreferredSize(new Dimension(75,75));
// Line of interest, adding the listener
buttons[i][j].addActionListener(new CustomActionListener(buttons[i][j]));
bigPanel.add(buttons[i][j]);
}
}
}
}
class CustomActionListener implements ActionListener
{
public int a;
public int b;
public JButton button;
CustomActionListener(JButton a)
{
button = a;
}
public void actionPerformed(ActionEvent e)
{
changeButton(a, b, CurrPlayer.CROSSES);
}
public void changeButton(int a, int b, CurrPlayer player)
{
if (player == CurrPlayer.NOUGHTS)
{
Icon icon = new ImageIcon("Nought.jpg");
button.setIcon(icon);
}
else
{
Icon icon = new ImageIcon("Cross.jpg");
button.setIcon(icon);
}
}
}
Change your CustomActionListener to following will solve this problem
class CustomActionListener implements ActionListener {
public int a;
public int b;
CustomActionListener()
{
}
public void actionPerformed(ActionEvent e)
{
JButton button = (JButton) e.getSource();
changeButton(a, b, CurrPlayer.CROSSES, button);
}
public void changeButton(int a, int b, CurrPlayer player, JButton button)
{
if (player == CurrPlayer.NOUGHTS)
{
Icon icon = new ImageIcon("Nought.jpg");
button.setIcon(icon);
}
else
{
Icon icon = new ImageIcon("Cross.jpg");
button.setIcon(icon);
}
}
}
You can get JButton reference using actionEvent.getSource() method.
And add action listener to buttons as below
buttons[i][j].addActionListener(new CustomActionListener());
Hope this'll help you.
So, i made a button like this
parameter nomor in LoadPlanet and LoadRR is parameter to show some data to textbox.
my code is like this
the button appear correctly, but if i clicked the buttons, all of them show data from the last data which supposed to be data in last button.
-> a result from tblplanet.JmlPlanet() is 8, so the parameter was like LoadPlanet(8), so that every button show 8th data.
my question is how to make the parameter in sequence, so the button can show data correctly? Any ideas?
public void createButton() {
for (i = 0; i < tblplanet.JmlPlanet(); i++) {
tblplanet.draw(i + 1);
planet_name = tblplanet.getNama_planet();
JButton PlanetJButton = new JButton();
PlanetJButton.setBounds(10, 5 + (i * 35), 95, 26);
PlanetJButton.setText(planet_name);
PanelButton.add(PlanetJButton);
PlanetJButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
for (int i = 0; i < tblplanet.JmlPlanet(); i++) {
nomor = i;
LoadPlanet(nomor);
LoadRR(nomor);
}
}
});
}
}
Create a class which implements ActionListener and takes a parameter (int) of the planet that it represents
public class PlanetActionListener implements ActionListener {
private final int planet;
public PlanetActionListener(int planet) {
this.planet = planet;
}
#Override
public void actionPerformed(ActionEvent e) {
LoadPlanet(planet);
LoadRR(planet);
}
}
Then simply add the ActionListener to your button
PlanetJButton.addActionListener(new PlanetActionListener(i));
Depending on how you code is structured, you may need to make the PlanetActionListener an inner class so it can access the appropriate methods. See Nested Classes for more details
I have:
for (int i = 0; i <= 9; i++) {
JButton c = new JButton();
c.setText(Integer.toString(i));
ActionListener l = new NumericButtonListener(i);
c.addActionListener(l);
buttonGrid.add(c); }
So basically, some code that creates a grid of numbers. How can I map my pane to allow hitting the appropriate number and trigger my NumericButtonListener?
You can use keyBindings and assign one common Action for the specific key.
Make use of button's doClick() function to generate an Action event and listens to it. You will need to invoke this function on the specific button to which mapped key is pressed. For example:
Action generateClick = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
JButton butt = (JButton) e.getSource();
butt.doClick();
}
};
Use keyBinding for each button. See tutorial for KeyBindings
For example add next code in creation:
c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(Integer.toString(i)), "doSomething");
c.getActionMap ().put("doSomething", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println(c.getText());
}
});
Hey all I can change the text of 1 single button easily with "final" but I need to create lots of buttons for a flight booking system, and when the buttons are more, final doesnt work ...
JButton btnBookFlight;
eco = new EconomyClass();
eco.setSeats(5);
for(int i=0;i<20;i++){
btnBookFlight = new JButton("Book" +i);
btnBookFlight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
btnBookFlight.setBackground(Color.RED);
btnBookFlight.setOpaque(true);
btnBookFlight.setText("Clicked");
}
});
btnBookFlight.setBounds(77, 351, 100, 23);
contentPane.add(btnBookFlight);
}
I would be glad if you can suggest me any trick to get over this.I want to change a buttons color or text when it is clicked or maybe some other cool effects when mouse over but for now only text or color will be enough =).Thanks for your time!
Use the source of the ActionEvent in the ActionListener
btnBookFlight.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton)event.getSource();
button.setBackground(Color.RED);
...
}
});
btnBookFlight has to be final for the inner class (ActionListener) to access it.
From JLS 8.1.3
Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.
If this is not permitted, then the JButton may be accessed using the source component of the ActionEvent itself using getSource.
However, that said, the simplest solution would be to move the JButton declaration within the scope of the for loop and make it final:
for (int i = 0; i < 20; i++) {
final JButton btnBookFlight = new JButton("Book" + i);
btnBookFlight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
btnBookFlight.setBackground(Color.RED);
...
}
});
}
Just avoid using anonymous classes for your action listener and the final constraint will disappear.
What I mean is use:
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton src = (JButton)e.getSource();
// do what you want
}
}
I'm creating a basic calculator using MVC. So far I'm adapting a tutorial which merely sums two user entered values together.
Currently each button I'm adding to the view has it's own listener, which is ok. However, the controller as per the tutorial has a single ActionListener inner class per button. This repeats a huge amount of code.
How can I create a single ActionListener class for all buttons pressed, and use a case statement on the id of the button pressed?
Registering the oneButton in the View
void oneListener(ActionListener listenForOneButton){
oneButton.addActionListener(listenForOneButton);
}
Implementing the ActionListener for the oneButton in the Controller inner class
class oneListener implements ActionListener{
public void actionPerformed(ActionEvent e){
int previousNumber, displayNumber = 0;
try{
previousNumber = theView.getPreviousDisplayNumber();
displayNumber = previousNumber+1;
theView.setDisplayNumber(displayNumber);
}
catch(NumberFormatException ex){
System.out.println(ex);
theView.displayErrorMessage("You Need to Enter Integers");
}
}
}
Start with class which implements ActionListener...
public class CalculatorHandler implements ActionListener{
public static final String ADD_ACTION_COMMAND = "Action.add";
public void actionPerformed(ActionEvent e){
if (ADD_ACTION_COMMAND.equals(e.getActionCommand()) {
// Do your addition...
} else if ...
}
}
It's best to define the action commands that this class can handle is constants, thus removing any ambiguity...
Next, in the class that holds the buttons, create an instance of the ActionListener...
CalculatorHandler handler = new CalculatorHandler();
Then create you buttons as per usual and register the handler...
JButton plus = new JButton("+");
plus.setActionCommand(CalculatorHandler.ADD_ACTION_COMMAND);
plus.addActionListener(handler);
The only problem with this approach, IMHO, is that it can create a monster if-else statement which may become difficult to maintain.
To my mind, I'd create some kind of model/builder that contained a series of helper methods (like add(Number), subtract(Number) etc) and use Actions API for the individual actions for each button...but that's just me...
public class SingleActionListener implements ActionListener {
public void initializeButtons() {
JButton[] buttons = new JButton[4];
String[] buttonNames = new String[] {"button1", "button2", "button3", "button4"};
for (int i = 0; i < 4; i++) {
buttons[i] = new JButton(buttonNames[i]);
}
}
public void addActionListenersToButtons() {
for (int i = 0; i < 4; i++) {
buttons[i].addActionListener(this);
}
}
public void actionPerformedd(ActionEvent actionEvent) {
if (actionEvent.getSource() == buttons[0]) {
//Do required tasks.
}
if (actionEvent.getSource() == buttons[1]) {
//Do required tasks.
}
if (actionEvent.getSource() == buttons[2]) {
//Do required tasks.
}
if (actionEvent.getSource() == buttons[3]) {
//Do required tasks.
}
}
}