简体   繁体   中英

How to remove an inner class ActionListener?

I am making a text based game, but I am having a rather large problem. This problem is that when I assign a new ActionListener to a button that already has an ActionListener assigned to it, it does both of the actions. Here's my code:

       while(shouldLoop) {
       if(Player.loc == 1) {
       left.setText("Do nothing");
       left.addActionListener(new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent e) {
           nar1.setText("You are still in a dungeon."); //Here's my first assignment
       }
       });
       right.setText("Pick the lock");
       right.addActionListener(new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent e) {
               Player.loc = 2;
           }
       });
       } if(Player.loc == 2) {
               nar1.setText("You are now outside");
               nar2.setText("the door. What now?");
               forward.addActionListener(new ActionListener() {
                   @Override
                   public void actionPerformed(ActionEvent e) {
                       nar1.setText("You hear a guard.");
                       nar2.setText("What do you do now?");
                       Player.loc = 3;
       }
               });
               left.addActionListener(new ActionListener() {   //Here's another
                   @Override                                   //assignment to
                   public void actionPerformed(ActionEvent e) {//the same button
                       nar1.setText("You hear a guard.");      //so when I press
                       nar2.setText("What do you do now?");    //it here, it
                       Player.loc = 3;                         //performs the
                   }                                           //original assignment
               });
               right.addActionListener(new ActionListener() {
                   @Override
                   public void actionPerformed(ActionEvent e) {
                       nar1.setText("You hear a guard.");
                       nar2.setText("What do you do now?");
                       Player.loc = 3;
                   }
               });
               right.setText(rgt);
               forward.setText(fwd);
               back.setText(bck);
               left.setText(lft);
               forward.setVisible(true);
       } if(Player.loc == 3) {
           forward.setVisible(false);
           right.setText("Sneak around him!");
           left.setText("Fight him!");
       }

Thanks for helping,

billofbong

您为什么不只将addActionListener代码提升到while循环之外?

Anonymous inner class listeners look nice in quick and dirty example code, but, in practice, they are a horrible idea. You are learning one of the reasons. Other reasons are that they can't readily be subclassed or modified via Dependency Injection types of things, can't readily be shared (say a button, a toolbar icon, and a menu do the same thing), can't readily be enabled / disabled, (say, "Save As" should be disabled cause nothing is open) etc...

For this use case, break them out into some series of actual Listeners, perhaps organized in a class, array, or some Enums, so they can get swapped in and out.

You are mixing data with code in a bad way by hard-coding the logic of your program in the program itself, and this is the main source of your current and future problems. This won't work, at least not without a lot of kludges.

I suggest you try to separate your data out of your code and make your program more MVC-ish, which stands Model-View-Controller (or one of its many variants). For instance the logic of the program is held by the Model and this includes the non-visualized map of the land being explored, the position of the player in this map, his companions, and your inventory of items that you've collected. So you will likely have several non-GUI classes such as Player, Map, Item (this may be an interface), Room, etc... The Map itself, the possible items, there locations, will be specified in a data file, perhaps a text file for a simple program or a database for a more complex one, and you will need classes to read and parse this file(s).

The View of your program is your GUI, and it should be as dumb as possible. Here is where you'll have your buttons, your text display, and if fancy, a graphical display of your game. No program logic goes in here. None.

The Control will be the Action Listeners that you add to your JButtons and any other code that has to deal with handling user input. But this code could be relatively simple, and it's main task is to pass user interactions to the model. So for instance if the left button is pressed, it may be simply something like

model.leftButtonPress();

Then the model will decide what to do with a left button press, if anything. The model will know where you are in the game for instance, if there's a door to your left or if it's a wall, and based on the state of the model your game will perform the requisite action.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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