gpt4 book ai didi

java - Java Swing MVC体系结构-Q与MCVE示例

转载 作者:行者123 更新时间:2023-11-29 04:55:07 25 4
gpt4 key购买 nike

给定多个问题excellent_informative_for_me-trashgod的答案,thatthat,以及其他几个无法回答我的问题,
一个关于ActionListeners位置的设计类应该如何设计
(以及总体MVC分离-下文会有更多说明)。

目录


问题解释
我的示例的文件结构树(4)
编译/清理源代码的命令(4)
资料来源


1.问题解释

我已经读过有关MVC的信息,并且我想我大部分都已经了解了,因此出于这个问题,让我们假设这是正确的。不赘述:


根据控制器的要求,从模型产生视图。
在大多数实现中,View可以访问Model实例。
控制器与用户交互,将更改传播到模型和视图。
模型是极其简化的数据存储容器。
可以通过View进行观察。


现在,我的困惑与ActionListeners有关-应该注册哪个类-并且依次包含-按钮的代码,或者实际上是大多数View元素的代码,它们实际上不仅仅是指示器,而是模型操纵器?

假设,我们在视图中有两个项目-用于更改模型数据的按钮,以及仅用于更改视图外观的一些可视项目。让代码负责更改View类中的View外观似乎是合理的。我的问题与第一种情况有关。我有几个想法:


View创建按钮,因此在View中创建ActionListeners并同时注册回调很自然。但这要求View具有与模型相关的代码,从而破坏封装。 View应该只了解底层的Controller或Model,仅通过Observer与之交谈。
我可以公开按钮等View项目,并从Controller将ActionListeners附加到它们,但这又破坏了封装。
我可以为每个按钮实现某种程度的回调-View会问控制器是否有任何代码应该为给定的按钮名称注册为ActionListener,但这似乎过于复杂,并且需要在控制器和视图之间进行名称同步。
我可以假设,理智的;),TableFactory中的按钮可以公开,允许将ActionListeners注入任何代码。
控制器可以替换整个View项(创建按钮并替换现有的按钮),但这似乎很疯狂,因为它不是它的角色


2.我的示例的文件结构树(4)

.
└── test
├── controllers
│   └── Controller.java
├── models
│   └── Model.java
├── resources
│   └── a.properties
├── Something.java
└── views
├── TableFactory.java
└── View.java


3.编译/清理源代码命令(4)

编译:


javac测试/Something.java测试/模型/*.java测试/控制器/*.java测试/视图/*.java


运行:


java test.Something


清洁:


找 。 -iname“ * .class” -exec rm {} \;


4.来源

该代码还包含国际化存根,对此我提出了单独的问题,这些行已明确标记,并且对答案没有任何影响。

控制器=> Controller.java

package test.controllers;
import test.models.Model;
import test.views.View;
public class Controller {
// Stub - doing nothing for now.
}


型号=> Model.java

package test.models;
import java.util.Observable;
public class Model extends Observable {
}


Something.java

package test;

import test.views.View;
import test.models.Model;
import test.controllers.Controller;

public class Something {

Model m;
View v;
Controller c;

Something() {
initModel();
initView();
initController();
}

private void initModel() {
m = new Model();
}

private void initView() {
v = new View(m);
}
private void initController() {
c = new Controller(m, v);
}

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
Something it = new Something();
}
});
}
}


查看=> View.java

package test.views;

import java.awt.*; // layouts
import javax.swing.*; // JPanel

import java.util.Observer; // MVC => model
import java.util.Observable; // MVC => model
import test.models.Model; // MVC => model

import test.views.TableFactory;

public class View {

private JFrame root;
private Model model;
public JPanel root_panel;

public View(Model model){
root = new JFrame("some tests");
root.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
root_panel = new JPanel();

root_panel.add(new TableFactory(new String[]{"a", "b", "c"}));

this.model = model;
this.model.addObserver(new ModelObserver());

root.add(root_panel);
root.pack();
root.setLocationRelativeTo(null);
root.setVisible(true);
}
}

class ModelObserver implements Observer {

@Override
public void update(Observable o, Object arg) {
System.out.print(arg.toString());
System.out.print(o.toString());
}
}


查看=> TableFactory.java

package test.views;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class TableFactory extends JPanel {

private String[] cols;
private String[] buttonNames;
private Map<String, JButton> buttons;
private JTable table;

TableFactory(String[] cols){

this.cols = cols;
buttonNames = new String[]{"THIS", "ARE", "BUTTONS"};
commonInit();
}
TableFactory(String[] cols, String[] buttons){

this.cols = cols;
this.buttonNames = buttons;
commonInit();
}

private void commonInit(){

this.buttons = makeButtonMap(buttonNames);
DefaultTableModel model = new DefaultTableModel();
this.table = new JTable(model);
for (String col: this.cols)
model.addColumn(col);

setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

JPanel buttons_container = new JPanel(new GridLayout(1, 0));
for (String name : buttonNames){
buttons_container.add(buttons.get(name));
}

JScrollPane table_container = new JScrollPane(table);

this.removeAll();
this.add(buttons_container);
this.add(table_container);
this.repaint();
}

private Map<String, JButton> makeButtonMap(String[] cols){
Map<String, JButton> buttons = new HashMap<String, JButton>(cols.length);
for (String name : cols){
buttons.put(name, new JButton(name));
}
return buttons;
}
}




编辑(针对下面的评论)



下一个参考资料来源 here

经过一番思考后,我理解了奥利维尔的评论,后来理解了关于鳗鱼的详细信息的气垫船…… javax.swing.Action => setAction是我的选择。控制器访问View的JPanels,获取对包含按钮或任何JComponent的地图的引用,并对其添加操作。 View不知道Controllers代码中的内容。当我使它很好地工作时,我将更新此答案,因此任何在这里绊倒的人都可以使用它。

令我担心的只有两件事(虽然很少见,但仍然如此):


因为我公开了View的添加动作的方法,所以实际上我相信任何人都只能从控制器或视图添加它。但是模型可以访问视图了吗?它也可以覆盖动作。
也是。如果我设置了某个对象的动作,然后又忘记从另一个地方设置另一个动作,那么它就消失了,这可能会使调试变得困难。

最佳答案

Model–View–Controller模式为no panacea时,它是Swing应用程序设计中的循环模式。如here所述,Swing控制组件通常是视图包含层次结构的一部分:Swing应用程序的控制器可能无事可做,只是将这些组件连接到相关的侦听器; Action实例(“可用于从组件中分离功能和状态”)特别方便。在此example中,Reset处理程序(简单的ActionListener)嵌套在控制器中,但也可以将其作为Action从模型中导出。按照here的建议,您可能必须尝试不同的设计。 here引用了几种方法。

关于java - Java Swing MVC体系结构-Q与MCVE示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34089447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com