【问题标题】:How to call a method in controller from the view?如何从视图调用控制器中的方法?
【发布时间】:2020-05-25 11:22:57
【问题描述】:

在我看来,我已经覆盖了一个 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

【问题讨论】:

  • 由于该方法不是静态的,因此您需要在视图类中引用 MapController。
  • 如果 1) 有什么让您感到困惑或 2) 有什么对您有帮助,请对答案发表评论。请阅读someone answers

标签: java swing model-view-controller actionlistener


【解决方案1】:

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

为什么不简单地给 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);

            // .....
}

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-26
    • 2013-07-02
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多