OK, this is called an answer with overkill, so sorry for that, but here is a quick example that I whipped that tries to use a simple MVC template to do the trivial thing: click a button and change the text in the JTextField. This is unnecessary because you can do the same in just a few lines of code, but it illustrates some MVCs in separate files and how the model manages the state. Please ask questions if something is misleading!
The main class that unites everything and starts work:
import javax.swing.*;
public class SwingMvcTest {
private static void createAndShowUI() {
MvcModel model = new MvcModel();
MvcView view = new MvcView(model);
MvcControl control = new MvcControl(model);
view.setGuiControl(control);
McvMenu menu = new McvMenu(control);
JFrame frame = new JFrame("MVC");
frame.getContentPane().add(view.getMainPanel());
frame.setJMenuBar(menu.getMenuBar());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Presentation Class:
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();
public MvcView(MvcModel model) {
model.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(MvcModel.STATE_PROP_NAME)) {
stateField.setText(evt.getNewValue().toString());
}
}
});
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (control != null) {
control.startButtonActionPerformed(e);
}
}
});
JButton endButton = new JButton("End");
endButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (control != null) {
control.endButtonActionPerformed(e);
}
}
});
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);
}
public void setGuiControl(MvcControl control) {
this.control = control;
}
public JComponent getMainPanel() {
return mainPanel;
}
}
Control:
import java.awt.event.ActionEvent;
public class MvcControl {
private MvcModel model;
public MvcControl(MvcModel model) {
this.model = model;
}
public void startButtonActionPerformed(ActionEvent ae) {
model.setState(State.START);
}
public void endButtonActionPerformed(ActionEvent ae) {
model.setState(State.END);
}
}
The model uses the PropertyChangeSupport object, which allows other objects (in this View situation) to listen for state changes. Thus, the model is actually our “observable”, while the view is “observer”
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;
pcSupport.firePropertyChange(STATE_PROP_NAME, oldState, state);
}
public State getState() {
return state;
}
public String getStateText() {
return state.getText();
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
}
enum, 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;
}
}
edit: , , SwingMcvTest. , - , , . :
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;
}
}
, , ! Rover Goldberg .