Java:按钮封装

Java: Button Encapsulation

所以我想要完成的是将 ActionListener 添加到另一个 class 中定义的按钮,而不破坏此按钮的封装。

我的 GUI class:

public class GUI extends JFrame {  

    private JButton button; 

    public GUI () { 
        this.button = new JButton ();
    }

    public void setText (Text text) {
        this.button.setText (text);
    }

    public JButton getButton () {
        return this.button;
    }    
}

我的游戏class:

public class Game { 

    private GUI gui;  

    public Game () {
        this.gui = new GUI ();
        this.gui.getButton ().addActionListener (new ActionListener () {
            public void actionPerformed (ActionEvent evt) {
                play ();                       
            }
        });  
    }

    public void play () {
        this.gui.setText ("Play");
    }
}

然后我在 Main class 中调用一个新的 Game 实例。

我想去掉 GUI class 中的 getter,否则使用类似的文本 setter 或 setter 是没有意义的。

当我将 ActionListener 添加到 GUI 构造函数时,我无权访问 Game 方法。有没有我没看到的解决方案?

GUI 将动作侦听器添加到按钮,让 Game 创建动作侦听器:

public class GUI extends JFrame { 

    public void addActionListenerToButton(ActionListener listener) {
        button.addActionListener(listener);
    }

    ....

}

public class Game { 

    private GUI gui;  

    public Game () {
        this.gui = new GUI ();
        this.gui.addActionListenerToButton (new ActionListener () {
            public void actionPerformed (ActionEvent evt) {
                play ();                       
            }
        });  
    }

    ...
}

或者只传入功能接口而不是完全构建的 ActionListener

通常当我这样做时,我会添加一个描述视图 (GUI) 的界面,然后让视图实现该界面。

public interface MyView {
    void addActionListener( ActionListener l );
}

和视图:

public class GameGui implements MyView {
   // lots o' stuff

    public void addActionListener( ActionListener l ) {
       button.addActionListener( l );
    }
}

那么您的主要代码就不会依赖于您实际实现的视图类型。

public class Main {
    public static void main( String... args ) {
       SwingUtils.invokeLater( Main::startGui );
    }

    public static void startGui() {
       MyView gui = new GameGui();
       gui.addActionListener( ... );
    }
}

不要忘记 Swing 不是线程安全的,必须在 EDT 上调用。