繁体   English   中英

使用removeActionListener但不删除-JAVA

[英]Using removeActionListener but not removing - JAVA

我已经创建了Tic-Tac-Toe游戏的一部分,并且我试图确保一旦开始游戏,“ Player VS Player”按钮将被禁用。 我对Java swing和所有图形都是陌生的,因此,请提供任何帮助。 我使用了.removeActionListener,但似乎什么也没做(或我注意到的任何事情)。 我的代码对某些人来说可能看起来很糟糕,但是正如我所说,我对此并不陌生。 现在可能不需要某些导入,但是我计划以后再使用它们。 提前致谢!

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.");
    }
  }
}

编辑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());
        }

      }
    }
  }

问题是,这不会禁用按钮

我的代码有几个问题,但是就您的问题而言,有两个主要问题:

  • 首先,正如克里斯蒂安(Christian)所指出的,您没有添加和删除同一实例。 我不确定是否可以通过给类一个equals和hashCode重写来缓解这种情况,我必须对此进行测试。
  • 但更重要的是,您似乎希望类的actionPerformed在您未将其添加到任何按钮时起作用。 在哪里看不到addActionListener(this) 话虽如此,我试图避免使我的GUI“视图”类实现侦听器接口。
  • 更好的解决方案可能是通过setAction(...)方法交换JButton AbstractActions。 可以将AbstractAction视为类固醇上的ActionListener,因为它们可以执行ActionListener可以执行的所有操作,然后执行某些操作。 这样做,您将不必担心删除以前的侦听器,因为一个按钮可以只有一个动作。

其他事宜:

  • 您的程序严重使用了static修饰符。 尽管静态字段和方法在小型程序中可能无关紧要,但由于它们无法“很好地”扩展,因此它们不是一种好习惯。 换句话说,如果您创建大型而复杂的程序(如果您坚持使用Java,则可以),则过多使用静态字段和方法会增加潜在的复杂性并限制程序类的继承潜力,从而使它们非常困难调试或增强。 避免过度使用static修饰符是一个好习惯,除非在某些情况下确实需要使用它。
  • 您正在将Swing GUI与控制台程序混合使用,这是很危险的事情。 更好的办法是通过GUI获取所有用户输入,并将控制台输出仅用于调试目的(如果有的话)。

编辑
是的,如果您覆盖equals和hashCode以便一种类型的所有侦听器都相同,则可以在尝试执行操作时将其删除。

例如,检查以下测试代码:

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();
   }
}

话虽如此,我不建议您这样做,而是通过setAction(...)交换AbstractActions。


编辑2
我是个白痴,没有认真阅读您的问题。 如果这是您的目标:

并且我正在尝试确保在游戏开始后禁用“玩家VS玩家”按钮:

然后,您所需要做的就是设置按钮禁用其“操作”

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);
   }
}

您应该使用同一实例来调用添加和删除。 因此将听众存储在一个字段中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM