我想在同一个包下的不同类中将Jframe中的逻辑与Jframe分开。但是,当我为Jframe组件添加功能(如按钮)时,它会添加到Jframe文件中。而且我无法从那里访问我的逻辑文件中的对象。什么是分离逻辑和图形的正确方法?在Netbeans中从Jframe文件中分离逻辑
回答
你能更具体吗?让我们给它一个上下文。假设我只有一个对象包含int的数据,Jframe包含一个我希望它将数据添加到1的按钮。我应该如何设置系统?
这基本上描述了一个模式,这个模式是负责控制逻辑,并为其他利益相关方所需要的功能与它
工作所以,你可能用一个简单的合同开始...
public interface DataModel {
public void add();
public int getData();
}
你,我会再创建一个abstract
版本,完成大部分锅炉板工作模式......
public abstract class AbstractDataModel implements DataModel {
private int data;
public AbstractDataModel(int value) {
this.data = value;
}
public void add(int delta) {
data += delta;
}
@Override
public int getData() {
return data;
}
}
,然后让我创建简单的具体实现......
public class AddByOneDataModel extends AbstractDataModel {
public AddByOneDataModel(int value) {
super(value);
}
@Override
public void add() {
add(1);
}
}
,或者如果你想成为真懒,你可以只是做...
public class DeltaDataModel extends AbstractDataModel {
private int delta;
public DeltaDataModel(int delta, int value) {
super(value);
this.delta = delta;
}
@Override
public void add() {
add(delta);
}
}
,但到目前为止,用户界面不是参与任何的话,也就没有在意,只会一味的想要的DataModel
一个实例然后你的用户界面看起来可能像...
public class TestPane extends JPanel {
private DataModel model;
private JButton add;
public TestPane() {
//...
add = new JButton("Add");
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getModel().add();
int data = getModel().getData();
// Update the UI in some meaningful way...
}
});
//...
}
public void setModel(DataModel model) {
this.model = model;
}
public DataModel getModel() {
return model;
}
}
那么这将让你做的事情一样......
TestPane pane = new TestPane();
pane.setModel(new DeltaDataModel(0, 100));
,它允许您指定要使用(因为谁知道你想要做什么模型的实际功能在未来)
但我仍然有点困惑如何视图和控制器部分彼此分离。你能基于上面的例子解释一下吗?另外,我看到MVC是3个对象,所以主要方法都不在这三个中,我是正确的吗?
如How MVC work with java swing GUI解释的,Java and GUI - Where do ActionListeners belong according to MVC pattern?,Listener Placement Adhering to the Traditional (non-mediator) MVC Pattern和verious关于这个问题的其他的答案,Swing是MVC的实现,阿尔比特更像MVC,其中所述组件是自包含的视图和控制器和模型是动态
这使得很难尝试包装更传统的MVC。相反,我们使用一个视图的概念来处理一系列包含在容器中的组件,然后遵循某个特定的合同。
在一个更传统的MVC中,模型和视图不与每个MVC交互,他们彼此不知道任何事情,而是控制器保持关系。
Model ...
让我们回去更新我们的模型。为了方便MVC,我们需要提供一个Observer Pattern它,所以当模型更新(因为该模型可V2独立的控制器或视图的更新),它可以触发通知
public abstract class AbstractDataModel implements DataModel {
private List<ChangeListener> changeListeners;
private int data;
public AbstractDataModel(int value) {
this.data = value;
changeListeners = new ArrayList<>(25);
}
@Override
public void addChangeListener(ChangeListener listener) {
changeListeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
changeListeners.remove(listener);
}
protected void fireStateChanged() {
if (!changeListeners.isEmpty()) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : changeListeners) {
listener.stateChanged(evt);
}
}
}
public void add(int delta) {
data += delta;
fireStateChanged();
}
@Override
public int getData() {
return data;
}
}
public class DeltaDataModel extends AbstractDataModel {
private int delta;
public DeltaDataModel(int value, int delta) {
super(value);
this.delta = delta;
}
@Override
public void add() {
add(delta);
}
}
public class AddByOneDataModel extends DeltaDataModel {
public AddByOneDataModel(int value) {
super(value, 1);
}
}
查看..
接下来,我们来看看视图。首先我们为视图定义合同,这可以确保控制器只能执行合同所说的内容。
public interface AddView {
public static final String ADD_ACTION_COMMAND = "Action.add";
public void setData(int data);
public void addActionListener(ActionListener listener);
public void removeActionListener(ActionListener listener);
}
注:我也可能被诱惑加入getComponent
方法,它返回它的实现实际上使用实际JComponent
,但将回落到你想要做什么,是体现在一些其他的链接
和物理实现...
public class AddViewPane extends JPanel implements AddView {
private JButton btn;
private JLabel label;
public AddViewPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
btn = new JButton("Add");
label = new JLabel("...");
add(btn, gbc);
add(label, gbc);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireAddAction();
}
});
}
@Override
public void setData(int data) {
label.setText(NumberFormat.getNumberInstance().format(data));
}
@Override
public void addActionListener(ActionListener listener) {
listenerList.add(ActionListener.class, listener);
}
@Override
public void removeActionListener(ActionListener listener) {
listenerList.remove(ActionListener.class, listener);
}
protected void fireAddAction() {
ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
if (listeners.length > 0) {
ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ADD_ACTION_COMMAND);
for (ActionListener listener : listeners) {
listener.actionPerformed(evt);
}
}
}
}
控制器...
再次,从最低水平,建设funcitonality了
public interface AddController {
public DataModel getModel();
public AddView getView();
}
public class AbstractAddController implements AddController {
private AddView view;
private DataModel model;
public AbstractAddController(AddView view, DataModel model) {
this.view = view;
this.model = model;
view.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getModel().add();
}
});
model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
getView().setData(getModel().getData());
}
});
}
@Override
public DataModel getModel() {
return model;
}
@Override
public AddView getView() {
return view;
}
}
public class DefaultAddController extends AbstractAddController {
public DefaultAddController(AddView view, DataModel model) {
super(view, model);
}
}
将其组合在一起...
最后,你也许能够使用的东西像...
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DataModel model = new AddByOneDataModel(0);
AddViewPane view = new AddViewPane();
DefaultAddController controller = new DefaultAddController(view, model);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// This is where having a getComponent method in
// view interface would be helpful
frame.add(view);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
把它放在一起
- 1. 从java中的GUI中分离逻辑
- 2. 从逻辑中分离数据
- 3. JSP - 从逻辑中分离设计
- 4. 分离node.js中的文件服务器和socket.io逻辑
- 5. 从Backbone.Device分离模板逻辑
- 6. 分离业务逻辑
- 7. 业务逻辑分离
- 8. 从JFrame到Netbeans中的JPanel
- 9. 从表示中分离逻辑:HTTP变量名称?
- 10. C#,从业务逻辑中分离消息显示代码
- 11. 从字段中分离字的逻辑运算
- 12. 将socket.io事件逻辑分离到模块中
- 13. 在AngularJS中将业务逻辑从控制器中分离出来
- 14. 如何分离模型(业务逻辑和商店逻辑)?
- 15. PHP:分离业务逻辑和表达逻辑,值得吗?
- 16. 在C#中分离用户界面和逻辑
- 17. 在Linq/mvc4中建立和分离查询逻辑
- 18. 在PHP中正确分离逻辑/风格
- 19. 如何在我的Android游戏中分离UI和逻辑?
- 20. 在express/node.js中分离模型,逻辑和DAO
- 21. 在Java中使用Sikuli插件时使用逻辑(NetBeans)
- 22. 分离逻辑/ GUI和用户交互
- 23. 物理或逻辑分离我的dll?
- 24. 分离Drupal模块逻辑和UI
- 25. C#DAL与PL逻辑分离
- 26. 如何分离业务逻辑
- 27. 如何从一个JFrame的Netbeans中
- 28. 在CasperJS中分割测试文件 - 与它的逻辑挣扎
- 29. Linux中的条件文件逻辑
- 30. 如何从业务逻辑中分离远程数据访问(通过http)逻辑?
先看看[Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) ,但基本上你是在正确的轨道上。不要直接访问组件,而应考虑提供访问其状态的获取者(和设置者)。您可以使用接口作为控制器和视图之间的契约来描述控制器可以在视图中执行什么操作,并提供一些事件通知,以便在重要事件发生时视图可以通知控制器 – MadProgrammer
Swing本身是一种类型的MVC,试图强制一个纯粹的MVC只是要求头痛,相反,你应该专注于包装一个MVC围绕它的现有框架 – MadProgrammer
对于[示例](http://stackoverflow.com/questions/31576623/how-mvc -work-with-java-swing-gui/31576899#31576899),[example](http://stackoverflow.com/questions/26517856/java-and-gui-where-do-actionlisteners-belong-according-to- mvc-pattern/26518274#26518274),[example](http://stackoverflow.com/questions/31602113/listener-placement-adhering-to-the-traditional-non-mediator-mvc-pattern/31604919#31604919) – MadProgrammer