2016-03-01 47 views
0

我想在同一个包下的不同类中将Jframe中的逻辑与Jframe分开。但是,当我为Jframe组件添加功能(如按钮)时,它会添加到Jframe文件中。而且我无法从那里访问我的逻辑文件中的对象。什么是分离逻辑和图形的正确方法?在Netbeans中从Jframe文件中分离逻辑

+0

先看看[Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) ,但基本上你是在正确的轨道上。不要直接访问组件,而应考虑提供访问其状态的获取者(和设置者)。您可以使用接口作为控制器和视图之间的契约来描述控制器可以在视图中执行什么操作,并提供一些事件通知,以便在重要事件发生时视图可以通知控制器 – MadProgrammer

+0

Swing本身是一种类型的MVC,试图强制一个纯粹的MVC只是要求头痛,相反,你应该专注于包装一个MVC围绕它的现有框架 – MadProgrammer

+0

对于[示例](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

回答

0

你能更具体吗?让我们给它一个上下文。假设我只有一个对象包含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); 
    } 
}); 

把它放在一起