是否有更好的方式让JPanels进行沟通?

时间:2018-04-06 22:12:38

标签: java swing jframe jpanel

我正在制作一个完全由菜单/屏幕组成的游戏,您可以使用按钮进行交互,基本上是基于文本的游戏,但没有打字。为此,我一直在使用Swing创建基本UI following this video series.

为了让在一个面板中执行的操作影响另一个面板的状态,我已经按照教程创建了一个UIListener接口,它扩展了EventListener。当在一个JPanel中按下一个按钮时,将调用面板的fireUIEvent方法,该方法又调用接口的唯一方法uiEventOccurred,该方法在主JFrame类中的匿名类中实现。然后JFrame可以对事件做任何想做的事情,并相应地修改它包含的其他JPanel。

例如,我有一个代表该镇的小组。它有一个按钮,你点击它前往地牢。单击此按钮时,城镇面板将被地牢面板取代,该面板有一个按钮,您可以单击该按钮返回城镇。

我会发布相关课程:

主框架类

public class GameMainFrame extends JFrame{

   public JPanel rightPanel;

   public GameMainFrame(String title) {
      super(title);

      /* Setting The Overall Layout */
      setLayout(new BorderLayout());

      /* Creating Individual UI Panels */
      UIPanel uip_town = new Town_UI();
      UIPanel uip_dung = new Dungeon_UI();

      /* Creating A Nested Panel */
      rightPanel = new JPanel();
      rightPanel.setLayout(new BorderLayout());
      rightPanel.add(uip_text, BorderLayout.WEST);
      rightPanel.add(uip_town, BorderLayout.NORTH);

      /* Creating A Listener To React To Events From The UI Panels */
      uip_town.addUIListener(new UIListener() {
         public void uiEventOccurred(UIEvent event) {
            System.out.println("event text: " + event.getText());
            if (event.getText().equals("goto_dungeon")) {
               rightPanel.remove(uip_town);
               rightPanel.add(uip_dung, BorderLayout.NORTH);
               validate();
            } else if (event.getText().equals("goto_town")) {
               rightPanel.remove(uip_dung);
               rightPanel.add(uip_town, BorderLayout.NORTH);
               validate();
            }
         }
      });

      /* Adding Panels To The Content Pane Of The Frame */
      Container c = getContentPane();
      c.add(uip_info, BorderLayout.WEST);
      c.add(rightPanel, BorderLayout.CENTER);
   }
}

UIPanel类

public class UIPanel extends JPanel {

   private EventListenerList listenerList;

   public UIPanel() {
      listenerList = new EventListenerList();
   }

   public void fireUIEvent(UIEvent event) {
      Object[] listeners = listenerList.getListenerList();
      for (int i = 0; i < listeners.length; i += 2) { 
         if (listeners[i] == UIListener.class) { 
            ((UIListener) listeners[i + 1]).uiEventOccurred(event);
         }
      }
   }

   public void addUIListener(UIListener listener) {
      listenerList.add(UIListener.class, listener);
   }

   public void removeUIListener(UIListener listener) {
      listenerList.remove(UIListener.class, listener);
   }
}

Town_UI类

public class Town_UI extends UIPanel {

   public Town_UI() {
      Dimension size = getPreferredSize();
      size.height = 466;
      setPreferredSize(size); 

      setBorder(BorderFactory.createTitledBorder("Town"));   

      JButton btn_dungeon_enter = new JButton("Enter the dungeon");

      add(btn_dungeon_enter);  

      btn_dungeon_enter.addActionListener(new ActionListener() {      
         public void actionPerformed(ActionEvent e) {
            fireUIEvent(new UIEvent(this, "goto_dungeon"));
         }
      }); 
   }
}

Dungeon_UI类

public class Dungeon_UI extends UIPanel {

   public Dungeon_UI() {
      Dimension size = getPreferredSize();
      size.height = 466;
      setPreferredSize(size); 

      setBorder(BorderFactory.createTitledBorder("Dungeon"));

      JButton btn_town_return = new JButton("Return to town");

      add(btn_town_return);

      btn_town_return.addActionListener(new ActionListener() {            
         public void actionPerformed(ActionEvent e) {
            fireUIEvent(new UIEvent(this, "goto_town"));
         }        
      });      
   }
}

UIEvent对象

public class UIEvent extends EventObject {

   private String text; 

   public UIEvent(Object source, String text) {
      super(source);
      this.text = text;
   }

   public String getText() { 
      return text;
   }
}

UIListener界面

public interface UIListener extends EventListener {

   public void uiEventOccurred(UIEvent e);

}

我有两个问题。第一,它目前被窃听。当我运行应用程序时,Town_UI面板显示其按钮“Enter the dungeon”,点击它后框架正确更新,用Dungeon_UI面板替换Town_UI面板。但是,单击地牢面板上的“返回城镇”按钮不会执行任何操作。在尝试调试时,我发现原因在于UIPanel方法fireUIEvent。当按下“返回城镇”按钮时,正确调用此方法,但是当使用getListenerList创建Object数组时,该数组为空,因此它会跳过for循环并且不执行任何操作。因为我不熟悉Java中的ActionEvents和EventListeners,我不知道如何解决这个问题。

我的另一个问题是按下按钮时发生的所有行为都是在GameMainFrame类的匿名类中处理的。这意味着如果我想要一堆不同的按钮都做不同的事情(我计划实现),我需要匿名类中的一大堆条件来确定按下什么按钮并执行相应的行为。如果按钮行为可以在每个按钮的匿名ActionListener类中实现,我觉得它会更清晰,但我不确定我应该如何重构我的代码以便我可以执行此操作但也允许任何操作小组能够修改任何其他小组。

在教程中我看到他声称EventListeners的这个实现是你应该做的,以避免让你的代码成为一个老鼠的巢,但似乎这就是我的代码所针对的地方,如果我使用这个实现我我想做。

0 个答案:

没有答案