简体   繁体   中英

Calling methods from JButton actions in other classes

The problem I'm facing here is that I'm not sure how to have a JButton action result in the calling of a method many classes above and removed from itself.

To give some idea of scope and structure here, I am working on a ski resort management app. It features classes like SkiRun and Lift, both of which are used within a SkiResort class. The SkiResort holds the functionality to perform actions on these. Originally, I used a ResortApp class to perform the (console) interfacing, taking in user inputs and making modifications to the SkiResort accordingly.

I am now adding a GUI via the Swing library, and have a complicated structure of (obviously) a JFrame, which contains many JPanels, which each contain more JPanels, and some of those contain JButtons. These are all managed through a class named MountainManager that sets up the JFrame and components, and should perform the interfacing with the SkiResort. The real issue I face here is that I'm not sure how to have it so that when a JButton is pressed, for example, that call can be passed back up to the MountainManager it's contained in to be able to perform whatever action it's supposed to perform.

In the included diagram, the red line is the calling I'm trying to achieve. So far, all of the JFrames and Panels and such are called new, and have no functionality.

图,红线是我们想要的

As basic simple solution is to path a listener to the target Jbutton :

import java.awt.event.ActionListener;
import javax.swing.*;   

public class MountainManager {

    private int counter = 0;

    public MountainManager() {
        ActionListener actionListener = e -> {
            System.out.println("Button presssed "+ ++counter +" times");
        };
        new View(actionListener);
    }

    public static void main(String[] args) {
        new MountainManager();
    }
}

class View{

    private final ActionListener actionListener;

    public View(ActionListener actionListener) {

        this.actionListener = actionListener;
        JFrame f = new JFrame("Ski Resort");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.add(new MainPanel());
        f.pack();
        f.setVisible(true);
    }

    class MainPanel extends JPanel{

        MainPanel() {
            JButton testButton = new JButton("Click");
            testButton.addActionListener(actionListener);
            add(testButton);
        }
    }
} 

A better design can be achieved by using MVC pattern . Introduce a Model class, shared between View and MountainManage (the controller) and listen to changes in Model :

import javax.swing.*;
import javax.swing.event.ChangeListener;

public class MountainManager {

    public MountainManager() {

        Model model = new Model();
        model.setListener(e -> System.out.println("Button presssed "+ model.getClickCount() +" times"));
        new View(model);
    }

    public static void main(String[] args) {
        new MountainManager();
    }
}

class View{

    private final Model model;

    public View(Model model) {

        this.model = model;
        JFrame f = new JFrame("Ski Resort");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.add(new MainPanel());
        f.pack();
        f.setVisible(true);
    }

    class MainPanel extends JPanel{

        MainPanel() {
            JButton testButton = new JButton("Click");
            testButton.addActionListener(e->model.incrementClickCount());
            add(testButton);
        }
    }
}

class Model {

    private int clickCount=0;
    //todo: change to List<ChangeListener> to support multi listeners
    private ChangeListener listener;

    int getClickCount(){
        return clickCount;
    }

    void incrementClickCount(){
         clickCount++;
         notifyListener();
    }

    void notifyListener(){
        if(listener != null){
            listener.stateChanged(null);
        }
    }

    void setListener(ChangeListener listener) {
        this.listener = listener;
    }
}

(Test it online here )

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