I'm developing a GUI that is kinda like a menu to control an assembly line. When the program runs, it shows up the window with the first set of buttons. Clicking in a button should make this window disappear and should make another window appear with the previously chosen menu. How do I implement the action on the button? Both menus are in different classes and there's an extra class with the main function that, for now, only creates new objects and set the visibility of the first window to true.
Here are both of them:
Main one:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class InfInd {
public static void main(String[] args) {
Cliente c = new Cliente();
c.setVisible(true);
}
}
The first Menu:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Cliente extends JFrame implements ActionListener {
public JLabel titulo;
public JButton ordens;
public JButton listaordens;
public JButton stats;
public JButton desc;
public JButton sair;
public Cliente() {
titulo = new JLabel("Menu Cliente");
ordens = new JButton ("Ordens");
listaordens = new JButton("Lista Ordens");
stats = new JButton ("Estatísticas");
desc = new JButton ("Peças Descarregadas");
sair = new JButton ("Sair");
setLayout(null);
Dimension size1 = titulo.getPreferredSize();
Dimension size2 = ordens.getPreferredSize();
Dimension size3 = listaordens.getPreferredSize();
Dimension size4 = stats.getPreferredSize();
Dimension size5 = desc.getPreferredSize();
Dimension size6 = sair.getPreferredSize();
titulo.setBounds(100, 50, size1.width, size1.height);
ordens.setBounds(100, 100, size2.width, size2.height);
listaordens.setBounds(100, 150, size3.width, size3.height);
stats.setBounds(100, 200, size4.width, size4.height);
desc.setBounds(100, 250, size5.width, size5.height);
sair.setBounds(100, 300, size6.width, size6.height);
sair.addActionListener(this);
add(titulo);
add(ordens);
add(listaordens);
add(stats);
add(desc);
add(sair);
setSize(500, 500);
setTitle("Teste");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent out){
System.exit(0);
}
}
The second menu is similar to this one, only with different names for the buttons. The idea is to, for now, just show up the second menu by clicking on the "Ordens" button. Sorry of this seems quite noobish but I've only started with Java GUIs yesterday. Thank you all.
You could do something like this
public class MyFrame extends JFrame {
private JButton jbt = new JButton("Open Window");
private AnotherFrame jfrm = new AnotherFrame(); // another frame
public MyFrame(){
add(jbt);
add(jfrm); // add frame
jbt.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
jfrm.setVisibility(true); // when button clicked, set
} // visibility for other frame true
});
}
private AnotherFrame extends JFrame {
public AnotherFrame(){
}
}
}
Related
The following example creates a JFrame with JButton, JTextField and JLabel.
When the button is pressed it increments the value in the text field and label.
This example also creates a 2nd JFrame that is a copy of the first.
The button, text field and label is copied as well.
The issue at hand is the button on the copied frame still updates the text field and label on the original. The 'why' is fairly obvious and is because the code makes specific reference to the text field and label.
Although this isn't written in the best manner but it is a great example of the scenario in which I am addressing.
The objective is, without a major rewrite, what would be the least invasive way to have the copied button action update the copied test field and label instead of the original?
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.JTextField;
class ButtonTextFieldLabel extends JFrame
{
JButton bnt1 = new JButton("B1");
JTextField tf1 = new JTextField("1");
JLabel lbl1 = new JLabel("100");
public ButtonTextFieldLabel()
{
super("Main Frame");
setLayout(null);
bnt1.setBounds(50,100,120,40);
tf1.setBounds(300,100, 80,40);
lbl1.setBounds(200,100,80,40);
bnt1.addActionListener(new ListenerHolder(this));
add(bnt1);
add(tf1);
add(lbl1);
setSize(500,500);
makeCopy(this);
setVisible(true);
}
private void makeCopy(ButtonTextFieldLabel originalObj)
{
JFrame copyFrame = new JFrame();
copyFrame.setTitle("Copy of " + originalObj.getTitle());
copyFrame.setSize(originalObj.getSize());
copyFrame.setLocation(originalObj.getX()+100, originalObj.getY()+100);
copyFrame.setLayout(null);
JButton copyBnt1 = new JButton();
copyBnt1.setBounds(originalObj.bnt1.getBounds());
copyBnt1.setLabel(originalObj.bnt1.getLabel());
copyFrame.add(copyBnt1);
for (ActionListener al : originalObj.bnt1.getActionListeners())
{
copyBnt1.addActionListener(al);
}
JTextField copyTf1 = new JTextField();
copyTf1.setBounds(originalObj.tf1.getBounds());
copyTf1.setText(originalObj.tf1.getText());
JLabel copyLbl1 = new JLabel();
copyLbl1.setBounds(originalObj.lbl1.getBounds());
copyLbl1.setText(originalObj.lbl1.getText());
copyFrame.add(copyBnt1);
copyFrame.add(copyTf1);
copyFrame.add(copyLbl1);
copyFrame.setVisible(true);
}
public void runThis()
{
tf1.setText( Integer.toString(Integer.parseInt(tf1.getText())+1) );
lbl1.setText( Integer.toString(Integer.parseInt(lbl1.getText())+1) );
}
}
class ListenerHolder implements ActionListener
{
ButtonTextFieldLabel ph;
public ListenerHolder(ButtonTextFieldLabel ph)
{
this.ph = ph;
}
#Override
public void actionPerformed(ActionEvent arg0)
{
ph.runThis();
}
}
public class TestBTL
{
public static void main(String[] args){
new ButtonTextFieldLabel();
}
}
You already know the reason for the problem -- you're copying the original ActionListener, complete with its reference to the original GUI components. The overall solution is not to copy the action listener but rather to create your GUI's to hold and maintain their own unique state. One solution is rather than try to copy components via kludge, to create a self-contained GUI object that holds and updates its own state. You can create multiple GUI's using a factory method if desired.
For example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class TestBtl2 {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndDisplayFrame("Frame 1").setVisible(true);
createAndDisplayFrame("Frame 2").setVisible(true);
});
}
// Factory method
private static JFrame createAndDisplayFrame(String text) {
BtlPanel btlPanel = new BtlPanel();
JFrame frame = new JFrame(text);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(btlPanel);
frame.pack();
frame.setLocationByPlatform(true);
return frame;
}
}
class BtlPanel extends JPanel {
private int value = 0;
private JButton button1 = new JButton(new ButtonAction("Button 1"));
private JLabel label1 = new JLabel("00");
private JTextField textField1 = new JTextField("00");
public BtlPanel() {
textField1.setFocusable(false);
add(button1);
add(Box.createHorizontalStrut(20));
add(label1);
add(Box.createHorizontalStrut(20));
add(textField1);
setPreferredSize(new Dimension(300, 100));
}
public void incrementValue() {
value++;
String text = String.format("%02d", value);
label1.setText(text);
textField1.setText(text);
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
incrementValue();
}
}
}
Side Recommendations:
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Check out: The Use of Multiple JFrames, Good/Bad Practice?
I have an object ReminderGUI which has a JTextArea field. ReminderGUI represents an app which lets save and display reminders. When getReminderButton is clicked I want the app to find the reminder which was previously saved for this date and display it in the JTextArea (I'm not showing this functionality in the code snippet).
I'm having trouble with changing JTextArea text and the code below demonstrates it. Once getReminderButton is clicked then getReminderButtonHandler() is supposed to initialize a new blank JTextArea and then append it to some new text here. Why doesn't this work?
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ReminderGUI extends JFrame implements ActionListener{
private JButton getReminderButton;
private JTextArea reminderTextArea;
public ReminderGUI() {
super();
super.setLayout(new BorderLayout());
this.reminderTextArea = new JTextArea("Enter text");
this.getReminderButton = new JButton("Get reminder");
JPanel southPanel = new JPanel();
southPanel.add(getReminderButton, BorderLayout.SOUTH);
super.add(southPanel, BorderLayout.SOUTH);
super.add(reminderTextArea, BorderLayout.CENTER);
this.getReminderButton.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == this.getReminderButton) {
this.getReminderButtonHandler();
}
}
private void getReminderButtonHandler() {
this.reminderTextArea = new JTextArea("");
this.reminderTextArea.append("some new text here");
}
public static void main(String[] args) {
ReminderGUI rmg = new ReminderGUI();
rmg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
rmg.setSize(500, 300);
rmg.setVisible(true);
}
}
The problem is in this line: this.reminderTextArea = new JTextArea("Enter text"); you're creating a new TextArea
You can set it using the set method, like this: reminderTextArea.setText(text);
I have noticed that all JOptionPane method "interfere" with ActionListeners.
I need ActionListener to remain active after a JOptionPane has been opened.
For example:
I have a JButton, I register the mouse being pressed and draw the button red. Upon being released, I draw it blue.
If I just click it, the button will turn blue. Ok
If I hold it clicked, the button will stay red. Ok
If I click it and set it to open a JOptionPane dialog, it stays red, even though I have released the mouse. Not Ok
I haven't been able to find any documentation on this specific behaviour, can someone point me in the right direction?
I do really need to use JOptionPane.
One option -- queue the call to open the JOptionPane on the Swing event queue. This will delay the opening of the modal JOptionPane just a little bit, allowing other button actions to be performed.
Another option is to extract the JDialog from the JOptionPane, and call it in a non-modal way.
For example:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestOptionPane extends JPanel {
private static final Color FOREGROUND = Color.RED;
private static final Color PRESSED_FG = Color.BLUE;
private JButton button1 = new JButton(new Button1Action());
private JButton button2 = new JButton(new Button1Action());
public TestOptionPane() {
setPreferredSize(new Dimension(600, 450));
button1.getModel().addChangeListener(new ButtonModelListener(button1));
button1.setForeground(FOREGROUND);
add(button1);
button2.getModel().addChangeListener(new ButtonModelListener(button2));
button2.setForeground(FOREGROUND);
add(button2);
}
private class Button1Action extends AbstractAction {
public Button1Action() {
super("Queue JOptionPane on Swing event thread");
}
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(TestOptionPane.this, "hello");
});
}
}
private class Button2Action extends AbstractAction {
public Button2Action() {
super("Show non-modal JOptionPane");
}
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> {
Component parentComponent = TestOptionPane.this;
JOptionPane optionPane = new JOptionPane("Hello", JOptionPane.PLAIN_MESSAGE);
JDialog dialog = optionPane.createDialog(parentComponent, "Fubars Rule!");
dialog.setModalityType(ModalityType.MODELESS);
dialog.setLocationRelativeTo(parentComponent);
dialog.setVisible(true);
});
}
}
private class ButtonModelListener implements ChangeListener {
private JButton button;
public ButtonModelListener(JButton button) {
this.button = button;
}
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isPressed()) {
button.setForeground(PRESSED_FG);
} else {
button.setForeground(FOREGROUND);
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("TestOptionPane");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TestOptionPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
I probably have a really simple problem. I want to create two frames - mainfr (in the class called Pag) and dscrpt (in a class called Apras). I managed to create the first frame (mainfr) and the second frame (dscrpt) using button skaiciav from the frame mainfr. When question is how to come back to the first frame using the button griz located in frame dscrp?
package grap;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Pag implements ActionListener {
JFrame mainfr;
JFrame apras;
JLabel psl_apras;
JLabel galim_veiksm;
JLabel paspaud;
public Pag() {
//Create JFrame container
mainfr = new JFrame("Turinys");
//Choosing layout type
mainfr.setLayout(new FlowLayout());
//window resolution
mainfr.setSize(500, 300);
//Program terminates on close
mainfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Label's
psl_apras = new JLabel("Mokomoji programa");
galim_veiksm = new JLabel("Galimi veiksmai");
//adding them to main frame
mainfr.add(psl_apras);
mainfr.add(galim_veiksm);
//Button
JButton skaiciav = new JButton("Description");
//action listener
skaiciav.addActionListener(this);
//adding button to frame
mainfr.add(skaiciav);
//another label
paspaud = new JLabel("Press button");
//adding label to frame
mainfr.add(paspaud);
//making frame visible
mainfr.setVisible(true);
}
//action listener method
public void actionPerformed(ActionEvent a) {
if(a.getActionCommand().equals("Description"))
{
Apras.suk();
mainfr.setVisible(false);
}
//Started to get confused here
/*if(a.getActionCommand().equals("back")){
mainfr.setVisible(true);
apras.setVisible(false);
dscrp.dispose();
*/
}
public static void main (String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Pag();
}
});
}
}
Second class
package grap;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Apras {
static JFrame dscrp;
static void suk() {
dscrp = new JFrame("Description");
dscrp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame2.setLocationByPlatform(true);
dscrp.setBackground(Color.WHITE);
JButton griz = new JButton("back");
//griz.addActionListener();
dscrp.add(griz);
dscrp.setSize(500, 300);
dscrp.setVisible(true);
}
}
I have created part of a Tic-Tac-Toe game, and I am trying to make sure the "Player VS Player" button becomes disabled once a game is started. I am new to Java swing and all of the graphics, so please, any help is appreciated. I have used .removeActionListener, but it seems to not do anything (or anything I notice). My code probably looks very bad to some of you, but as I said, I am new to this. Some of the imports may not be needed now, but I plan on using them later.
Thanks in advance!
import java.util.Scanner;
import java.lang.Object;
import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import java.awt.Frame;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.text.JTextComponent;
import javax.swing.JTextField;
import java.lang.Thread;
import java.util.EventObject;
import java.awt.AWTEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowEvent;
import java.awt.Font;
import javax.swing.*;
class ticTacToe implements ActionListener
{
public static JFrame menuFrame = new JFrame("Tic-Tac-Toe");
public static JPanel menu = new JPanel();
public static JButton instruct = new JButton("Instructions"), pvp = new JButton("Player VS. Player"), pvc = new JButton("Player VS. Computer");
public static String pOne = "bla", pTwo = "bla";
public static boolean namesEntered = false;
public static JFrame pvpFrame = new JFrame (pOne+" "+"VS."+" "+pTwo);
public static JPanel board = new JPanel (), turns = new JPanel();
public static JLabel turn1 = new JLabel (pOne+" has taken 0 turn(s)."), turn2 = new JLabel (pTwo+" has taken 0 turn(s).");
public static JButton btn1 = new JButton (), btn2 = new JButton (), btn3 = new JButton (), btn4 = new JButton (), btn5 = new JButton (), btn6 = new JButton (), btn7 = new JButton (), btn8 = new JButton (), btn9 = new JButton ();
public static int choice = 3;
public static Font f = new Font("Arial", Font.PLAIN, 40);
public static void main (String[]args)
{
instruct.addActionListener(new Instructions());
pvp.addActionListener(new playerVSPlayer());
pvc.addActionListener(new Action());
menu();
}
public static void menu ()//the main menu of the game
{
menu.setLayout(new FlowLayout());//arranges the layout of the buttons on the panel
menu.add(instruct);//adds the instruction button
menu.add(pvp);//adds the player vs player button
menu.add(pvc);//adds the player vs computer button
menuFrame.add(menu);//creates the panel
menuFrame.setSize(450, 78);
menuFrame.setLocationRelativeTo(null);//sets the location to the centre of the screen
menuFrame.setVisible(true);//makes the menu visible
menuFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//extis program when window is closed
}
public void actionPerformed (ActionEvent e)//detection of the clicked button
{
if (e.getSource().equals(instruct))
{
instructions();
}
else if (e.getSource().equals(pvp))
{
if (e.getSource().equals(btn1))
{
btn1.setFont(f);
btn1.setText("X");
btn1.removeActionListener(new playerVSPlayer());
}
else
{
players();
if (!pOne.equals("0")&&!pTwo.equals("0"))
{
firstTurn();
}
if (namesEntered==true&&choice==1)
{
gameBoard();
btn1.addActionListener(new playerVSPlayer());
}
pvp.removeActionListener(new playerVSPlayer());
}
}
}
public static void instructions ()
{
JFrame frame = new JFrame ("Instructions");
frame.setVisible(true);
frame.setSize(300,145);
JLabel label = new JLabel ("The goal of this game is to be the first player that ");
JLabel label2 = new JLabel ("gets 3 X's or O's in a row diagonally, vertically, or");
JLabel label3 = new JLabel ("horizontally. It is possible to tie, by having all");
JLabel label4 = new JLabel ("spaces played with no spots left to win. Click a");
JLabel label5 = new JLabel ("space to enter your X or O.");
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
frame.add(panel);
panel.add(label);
panel.add(label2);
panel.add(label3);
panel.add(label4);
panel.add(label5);
}
public static void players ()
{
Scanner in = new Scanner (System.in);
System.out.println("Player One, please enter a word no longer than 4 letters, representing your username for this game.");
pOne = in.nextLine();
if (pOne.equals("0"))
{
System.out.println("You have cancelled the match. Please choose an option in the main menu, or close the main menu.");
}
else {
while (pOne.length()>4||pOne.length()<1)
{
System.out.println("Player One, your username MUST be between 1 and 4 letters long.");
pOne = in.nextLine();
}
}
if (!pOne.equals("0"))
{
System.out.println("Player Two, please enter a word no longer than 4 letters, representing your username for this game.");
pTwo = in.nextLine();
if (pTwo.equals("0"))
{
System.out.println("You have cancelled the match. Please choose an option in the main menu, or close the main menu.");
}
else {
while (pTwo.length()>4||pTwo.length()<1)
{
System.out.println("Player Two, your username MUST be between 1 and 4 letters long.");
pTwo = in.nextLine();
}
}
}
if (!pOne.equals("0")&&!pTwo.equals("0"))
{
namesEntered= true;
}
}
public static void gameBoard ()
{
pvpFrame = new JFrame (pOne+" "+"VS."+" "+pTwo);
pvpFrame.setLayout(new GridLayout());
pvpFrame.setVisible(true);
pvpFrame.setSize(600,400);
pvpFrame.setLocationRelativeTo(null);
board.setLayout(new GridLayout(3,3));
turns.setLayout(new FlowLayout());
pvpFrame.add(board);
pvpFrame.add(turns);
turn1 = new JLabel (pOne+" has taken 0 turns.");
turn2 = new JLabel (pTwo+" has taken 0 turns.");
turns.add(turn1);
turns.add(turn2);
board.add(btn1);
board.add(btn2);
board.add(btn3);
board.add(btn4);
board.add(btn5);
board.add(btn6);
board.add(btn7);
board.add(btn8);
board.add(btn9);
}
public static void firstTurn ()
{
Scanner in = new Scanner (System.in);
System.out.println(pOne+" will be X and "+pTwo+" will be O. Enter 1 if you would like to continue. Enter 0 if you would like to cancel this match and return to the main menu.");
choice = in.nextInt();
while (choice!=0&&choice!=1)
{
System.out.println("Your choice did not match 1 or 0. Please enter your choice again.");
choice = in.nextInt();
}
if (choice==0)
{
System.out.println("You have cancelled the match. Please choose an option in the main menu, or close the main menu.");
}
}
}
EDIT 1:
public void actionPerformed (ActionEvent e)//detection of the clicked button
{
if (e.getSource().equals(instruct))
{
instructions(); // This just runs the instruction panel
}
else if (e.getSource().equals(pvp))
{
if (e.getSource().equals(btn1))
{
btn1.setFont(f);
btn1.setText("X");
btn1.removeActionListener(new playerVSPlayer());
}
else
{
players();
if (!pOne.equals("0")&&!pTwo.equals("0"))
{
firstTurn();
}
if (namesEntered==true&&choice==1)
{
gameBoard();
pvp.setEnabled(false); // my goal here is to make the button no longer usable once the
//game starts, but I also need to make sure later that i can use the button once this game is closed
btn1.addActionListener(new playerVSPlayer());
}
}
}
}
The problem is, that does not disable the button
I have several issues with your code, but as far as your question is concerned, there are two main issues:
First as Christian points out, you are not adding and removing the same instance. I'm not sure if this can be alleviated by giving the class an equals and hashCode override, and I must test this.
But even more important, you seem to expect the class's actionPerformed to act, when you don't appear to add it to any buttons. No where do I see addActionListener(this). Having said that, I try to avoid making my GUI "view" classes implement listener interfaces.
A better solution perhaps would be swapping JButton AbstractActions via the setAction(...) method. Think of AbstractActions as if they were ActionListeners on steroids, since they can do everything that an ActionListener can do and then some. Do this and you won't have to worry about removing prior listeners since a button can have one and only one Action.
Other issues:
Your program grossly over-uses the static modifier. While static fields and methods probably won't matter in small programs, they're not a good habit to get into since they don't "scale" well. In other words, if you create large and complex programs (and if you stick with Java, you will), over-use of static fields and methods increases the potential complexity and limits the inheritance potential of your classes of your programs making them very difficult to debug or enhance. It's a good habit to avoid over-use of static modifier except in the certain situations where it is definitely called for.
You're mixing a Swing GUI with a console program which is a dangerous thing to do. Much better would be to get all user input via the GUI, and leave the console output for debugging purposes (if that) only.
Edit
Yep, if you override equals and hashCode so that all Listeners of one type are the same, then you can remove them as you're trying to do.
For example check this test code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class TestActionListeners extends JPanel {
private JButton button = new JButton("Button");
public TestActionListeners() {
add(button);
button.addActionListener(new Listener1());
}
private static void createAndShowGui() {
TestActionListeners mainPanel = new TestActionListeners();
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class Listener1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("in listener 1");
AbstractButton button = (AbstractButton) e.getSource();
button.removeActionListener(new Listener1());
button.addActionListener(new Listener2());
}
#Override
public boolean equals(Object obj) {
return obj instanceof Listener1;
}
#Override
public int hashCode() {
return Listener1.class.hashCode();
}
}
class Listener2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("in listener 2");
AbstractButton button = (AbstractButton) e.getSource();
button.removeActionListener(new Listener2());
button.addActionListener(new Listener1());
}
#Override
public boolean equals(Object obj) {
return obj instanceof Listener2;
}
#Override
public int hashCode() {
return Listener2.class.hashCode();
}
}
Having said this, I don't recommend that you do this but rather swap AbstractActions via setAction(...).
Edit 2
I'm an idiot for not carefully reading your question. If this is your goal:
and I am trying to make sure the "Player VS Player" button becomes disabled once a game is started:
Then all you need to do is set the button or its Action disabled. i.e.,
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class DisableAButton extends JPanel {
private JButton disableMeButton1 = new JButton("Disable Me 1");
private JButton disableMeButton2 = new JButton(new DisableMe2Action("Disable Me 2"));
public DisableAButton() {
disableMeButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
AbstractButton buttonSource = (AbstractButton) e.getSource();
JOptionPane.showMessageDialog(buttonSource, "DisableMe1 ActionListener!");
buttonSource.setEnabled(false);
}
});
add(disableMeButton1);
add(disableMeButton2);
}
private static void createAndShowGui() {
DisableAButton mainPanel = new DisableAButton();
JFrame frame = new JFrame("DisableAButton");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class DisableMe2Action extends AbstractAction {
public DisableMe2Action(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
JComponent source = (JComponent) e.getSource();
JOptionPane.showMessageDialog(source, "DisableMe2 Action!");
setEnabled(false);
}
}
you should use the same instance to call add and remove.
therefor store the listeners in a field