java - 如何从视图调用控制器中的方法?
问题描述
在我看来,我已经覆盖了一个 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
解决方案
尝试以静态方式调用控制器方法绝对不是答案,除非绝对必要,否则我不建议使用单例(正如另一个答案所建议的那样),因为根据堆栈溢出,单例使用可能会很棘手。单身人士不好吗?问/答。
为什么不简单地给 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”侦听器,因为这会不必要地增加程序复杂性。最好使用匿名内部侦听器,即调用控制器方法的侦听器。
推荐阅读
- vue.js - 如何在 VS Code 的 vue 文件中为 sass 启用自动完成/IntelliSence?
- typo3 - typo3 8 中不再有默认链接类?
- runnable - 返回类型为 void 的执行器服务
- java - 创建 Rss 文档时,带有重音符号的字符无法在 Java Server Pages 上写入
- sql - SQL 表关系
- r - R中光栅立方体可视化中的RGB颜色
- vector - 使用 iter().filter().collect() 而不是 Vec<&&String> 后如何获取 Vec<&String>
- mysql - 通过记录类型mysql表获取所有记录
- iphone - 如何在 Ionic 3 中隐藏键盘?
- unit-testing - 如何修复错误 import Vue from 'vue' 导致 SyntaxError: Unexpected identifier