Search code examples
javamodel-view-controllerjbuttonactionlistenerprivate

Dealing with MVC model, jbuttons and ActionListener's getSource() method


So i just stumbled upon this problem while coding my program using MVC. I have a private JButton in the View class. I wrote the method to add the listener to all respective buttons. However, when i'm trying to code the ActionPerformed() part it throws an error about JButton not being visible.

Setting JButton to public solves the problem completly, but is it the right thing to do? Is there another way of setting the ActionListener without making the JButton public?

public class learningView extends JFrame {
    private JButton viewButton = new JButton("View Resources");

    public void addButtonListener(ActionListener listenerForButtons) { 

    viewButton.addActionListener(listenerForButtons);
    saveButton.addActionListener(listenerForButtons);
    addButton.addActionListener(listenerForButtons);

    }
}

public class learningController {

    private learningModel theModel;
    private learningView theView;

    public learningController(learningModel theModel, learningView theView) {

    this.theModel = theModel;
    this.theView = theView;

    this.theView.addButtonListener(new buttonListener());

}

class buttonListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == theView.viewButton) {// This is where problem arises

        }

    }

}

}

Hastebin for view and controller classes (without model) for the convienience. http://www.hastebin.com/ecawolusal.avrasm


Solution

  • Since viewButton has private access to LearningVew, it will simply be inaccessible out of that classes context.

    Now, before you change the access level, you might consider changing your approach.

    Rather then adding an ActionListener to each button which notifies an external source, it might be simpler to have the view to monitor the buttons itself.

    Before you get up in arms over how this would break the MVC, the idea would be to then have the view raise a simpler, more dedicated event for the button in question, for example, viewButton could raise viewWasActivated or something, to which the controller would then respond.

    This would require you to define a interface contract for both the view and the controller so they knew what information they were capable of passing to each other and what events might be triggered. This protects the view controls and means you don't need to expose the unnecessarily.

    Which is demonstrated in more detail here.

    The other choice would be to use the actionCommand property of the buttons instead of comparing references of the buttons to the event source, but you would first need to check that the source of the action event was a button ... and I personally don't like "bulk" ActionListeners, they get messy real quickly...