首页 > 解决方案 > 如何从视图调用控制器中的方法?

问题描述

在我看来,我已经覆盖了一个 actionPerformed() 方法,在其中我想调用我的 Controller 中的方法 updateMap()。我试过写:MapController.updateMap(selected),但这给出了一个错误:不能从静态上下文中引用非静态方法'updateMap(int)'。

我尝试将 updateMap() 设为静态,但这给了我在 updateMap() 中的大量错误。我只想知道如何在 View 中的 actionPerformed() 方法中调用 Controller 的 updateMap()。

我的控制器:

package main.java.controllers;
import main.app.view.MapView;
import main.java.models.MapModel;
import org.w3c.dom.ls.LSOutput;

import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;

public class MapController {
    private MapView view;
    private MapModel model;

    public MapController(MapView view, MapModel model) {
        this.view = view;
        this.model = model;
        this.model.getAllRoutes();

        ArrayList<String> routes = model.getAllRoutes();
        this.view.getRouteComboBox().getSelectedItem();
        this.view.setComboBoxValues(routes);
        this.updateMap(2);
        this.view.setVisible(true);
    } //constructor end

    public void updateMap(int routeID){
        model.fillCoordinateListArray(routeID);
        Image image = null;
            try {
                URL url = new URL("https://maps.googleapis.com/maps/api/staticmap?" +
                        "&size=600x450" +
                        "&maptype=roadmap" +
                        this.model.parseCoordinates() +
                        //"San+Francisco,CA" + "%7C" +
                        //"&markers=label:1%7C40.702147,-74.015794" + "%7C" +

                        "&key=AIzaSyAbLM94WcbkB-cf_ubHXOHmCDSsNWEz7XE");
                image = ImageIO.read(url);
              //  System.out.print(url);
            } catch (IOException e) {
                System.out.println("Ongeldige URL");
                e.printStackTrace();
        }
        this.view.setImage(image);
        this.view.repaint();
    } //method end



      /*  public int getSelected(){
            return this.selected;
        } */


} //class end

我的观点:

package main.app.view;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;


import main.java.controllers.MapController;
import main.java.models.MapModel;
import main.resources.ConnectionManager;

public class MapView extends JPanel {
    public Image image;
    private JLabel jlImage;
    private static JButton jbOk;
    private ArrayList<String> comboBoxValues;
    private JComboBox routeComboBox = new JComboBox();
    //private JComboBox<ArrayList<>>;
    private ActionListener actionListener;

    public MapView(){
        super(new FlowLayout());
        setSize(900, 450);
        this.add(getRouteComboBox());
        jbOk = new JButton("OK");
        jbOk.setActionCommand("OK");
        ListenerOfActions listener = new ListenerOfActions();
        jbOk.addActionListener(listener);
        add(jbOk);

    } //constructor end

    public void setComboBoxValues(ArrayList<String> comboBoxValues) {
        this.comboBoxValues = comboBoxValues;
        for (String item: comboBoxValues) {
            routeComboBox.addItem( item );
        }
    }

    public void setImage(Image image){
        this.image = image;
    }


    public MapView getView(){
        jlImage = new JLabel(new ImageIcon(this.image));
        add(jlImage);
        return this;
    }

    public void addListenerOfActions(ActionListener listenForAction) {
        this.actionListener = listenForAction;
    }

    public JComboBox getRouteComboBox(){
        return routeComboBox;
    }

    class ListenerOfActions implements ActionListener {
        int selected = 0;

        @Override
        public void actionPerformed(ActionEvent e) {

            String actionCommand = e.getActionCommand();
            if(actionCommand.equals("OK")) {
                 int selected = getRouteComboBox().getSelectedIndex() + 1;
                 System.out.println(selected);
                System.out.println("print1");

                   MapController.updateMap(selected);
            }
            System.out.println("print2");

        }

        public int getSelected(){
            return this.selected;
        }


    } //class end
} //class end

标签: javaswingmodel-view-controlleractionlistener

解决方案


尝试以静态方式调用控制器方法绝对不是答案,除非绝对必要,否则我不建议使用单例(正如另一个答案所建议的那样),因为根据堆栈溢出,单例使用可能会很棘手。单身人士不好吗?问/答。

为什么不简单地给 MapView 一个 MapController 字段并通过可以在 MapController 构造函数中调用的 setter 方法传入实例?例如:

public class MapView {
    private MapController controller;
    // ...

    public MapView() {
        //......
    }

    public void setMapController(MapController controller) {
        this.controller = controller;
    }

    // then here you can call the instance methods as needed

}

并像这样连接起来:

public class MapController {

    public class MapController {
        private MapView view;
        private MapModel model;

        public MapController(MapView view, MapModel model) {
            this.view = view;
            this.model = model;    
            view.setMapController(this);

            // .....
}

由于在此示例中,控制器通过设置器参数而不是构造器参数传递到视图中,因此无法保证会发生这种连接。因此在视图中,在尝试调用控制器方法之前进行空测试是明智的,如果检测到空,可能会抛出对您和用户有意义的异常。

所以,再一次,这很糟糕:private static JButton jbOk;

使所有 GUI 组件实例化而不是静态的。我也更喜欢避免对整个 GUI 使用单个 ActionListener,即所谓的“switch-board”侦听器,因为这会不必要地增加程序复杂性。最好使用匿名内部侦听器,即调用控制器方法的侦听器。


推荐阅读