好的,这被称为过度矫正地回答,对此感到抱歉,但这是我快速举过的一个简单示例,尝试使用简单的MVC模式完成一些琐碎的事情:按下按钮并更改JTextField中的文本。这太过分了,因为您可以只用几行代码就可以完成相同的操作,但是它确实在单独的文件中说明了某些MVC以及模型如何控制状态。请问任何令人困惑的问题!
汇集所有内容并开始工作的主要课程:
import javax.swing.*;public class SwingMvcTest { private static void createAndShowUI() { // create the model/view/control and connect them together MvcModel model = new MvcModel(); MvcView view = new MvcView(model); MvcControl control = new MvcControl(model); view.setGuiControl(control); // EDIT: added menu capability McvMenu menu = new McvMenu(control); // create the GUI to display the view Jframe frame = new Jframe("MVC"); frame.getContentPane().add(view.getMainPanel()); // add view here frame.setJMenuBar(menu.getMenuBar()); // edit: added menu capability frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } // call Swing pre in a thread-safe manner per the tutorials public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); }}视图类:
import java.awt.*;import java.awt.event.*;import java.beans.*;import javax.swing.*;public class MvcView { private MvcControl control; private JTextField stateField = new JTextField(10); private JPanel mainPanel = new JPanel(); // holds the main GUI and its components public MvcView(MvcModel model) { // add a property change listener to the model to listen and // respond to changes in the model's state model.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { // if the state change is the one we're interested in... if (evt.getPropertyName().equals(MvcModel.STATE_PROP_NAME)) { stateField.setText(evt.getNewValue().toString()); // show it in the GUI } } }); JButton startButton = new JButton("Start"); startButton.addActionListener(new ActionListener() { // all the buttons do is call methods of the control public void actionPerformed(ActionEvent e) { if (control != null) { control.startButtonActionPerformed(e); // e.g., here } } }); JButton endButton = new JButton("End"); endButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (control != null) { control.endButtonActionPerformed(e); // e.g., and here } } }); // make our GUI pretty int gap = 10; JPanel buttonPanel = new JPanel(new GridLayout(1, 0, gap, 0)); buttonPanel.add(startButton); buttonPanel.add(endButton); JPanel statePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); statePanel.add(new JLabel("State:")); statePanel.add(Box.createHorizontalStrut(gap)); statePanel.add(stateField); mainPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap)); mainPanel.setLayout(new BorderLayout(gap, gap)); mainPanel.add(buttonPanel, BorderLayout.CENTER); mainPanel.add(statePanel, BorderLayout.PAGE_END); } // set the control for this view public void setGuiControl(MvcControl control) { this.control = control; } // get the main gui and its components for display public JComponent getMainPanel() { return mainPanel; }}控件:
import java.awt.event.ActionEvent;public class MvcControl { private MvcModel model; public MvcControl(MvcModel model) { this.model = model; } // all this simplistic control does is change the state of the model, that's it public void startButtonActionPerformed(ActionEvent ae) { model.setState(State.START); } public void endButtonActionPerformed(ActionEvent ae) { model.setState(State.END); }}该模型使用PropertyChangeSupport对象来允许其他对象(在这种情况下为View)侦听状态变化。因此,模型实际上是我们的“可观察”模型,而视图是“观察者”模型
import java.beans.*;public class MvcModel { public static final String STATE_PROP_NAME = "State"; private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this); private State state = State.NO_STATE; public void setState(State state) { State oldState = this.state; this.state = state; // notify all listeners that the state property has changed pcSupport.firePropertyChange(STATE_PROP_NAME, oldState, state); } public State getState() { return state; } public String getStateText() { return state.getText(); } // allow addition of listeners or observers public void addPropertyChangeListener(PropertyChangeListener listener) { pcSupport.addPropertyChangeListener(listener); }}一个简单的枚举State来封装state的概念:
public enum State { NO_STATE("No State"), START("Start"), END("End"); private String text; private State(String text) { this.text = text; } @Override public String toString() { return text; } public String getText() { return text; }}编辑:我看到您也提到了菜单,所以我添加了菜单支持,并添加了此类以及在SwingMcvTest类中添加了几行。请注意,由于代码分离,因此对GUI进行更改很简单,因为所有菜单所需要做的就是调用控制方法。它不需要了解模型或视图:
import java.awt.event.ActionEvent;import javax.swing.*;public class McvMenu { private JMenuBar menuBar = new JMenuBar(); private MvcControl control; @SuppressWarnings("serial") public McvMenu(MvcControl cntrl) { this.control = cntrl; JMenu menu = new JMenu("Change State"); menu.add(new JMenuItem(new AbstractAction("Start") { public void actionPerformed(ActionEvent ae) { if (control != null) { control.startButtonActionPerformed(ae); } } })); menu.add(new JMenuItem(new AbstractAction("End") { public void actionPerformed(ActionEvent ae) { if (control != null) { control.endButtonActionPerformed(ae); } } })); menuBar.add(menu); } public JMenuBar getMenuBar() { return menuBar; }}上帝,这是很多琐碎的代码!我提名自己和我的代码来获得本周的stackoverflow Rube Goldberg奖。



