我只需要回答具体应该看起来像这段代码与JPanel的变化。 我写道我可以使用没有MVC的CardLayout,但我不知道如何在MVC中做到这一点...如何将它应用到MainFrame?
您的控制器和模型代码不应该关心视图采用什么形式,无论是扩展JFrame,JPanel还是(可能最好)。 据推测,在上面的控件的actionPerformed方法中,视图,模型和控制器已经被创建并适当地“连接”。 在此actionPerformed方法中,您所做的只是向模型发送命令以更改其状态。 换句话说,控制器将调用模型上的方法来启动状态更改。 我通常有视图然后通过侦听模型的更改来响应。
这还没有完全“有线”,但我想样本代码看起来像下面的代码。 请注意,我更喜欢使用匿名内部类侦听器,它们是视图的一部分,并且它们自己调用Controller方法:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
public class SimpleMVC {
private static void createAndShowGui() {
SmvcView view = new SmvcView();
SmvcModel model = new SmvcModel();
new SmvcController(view, model);
view.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class SmvcView {
private JPanel mainPanel = new JPanel();
private CardLayout cardLayout = new CardLayout();
private JPanel cardPanel = new JPanel(cardLayout);
private ModelListener modelListener = new ModelListener();
private SmvcController controller;
private DefaultComboBoxModel comboModel = new DefaultComboBoxModel<>(
SmvcState.values());
private JComboBox stateCombo = new JComboBox<>(comboModel);
public SmvcView() {
stateCombo.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
DefaultListCellRenderer renderer = (DefaultListCellRenderer) super
.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
SmvcState state = (SmvcState) value;
if (state != null) {
value = state.getText();
renderer = (DefaultListCellRenderer) super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
}
return renderer;
}
});
stateCombo.addActionListener(evt -> {
SmvcState state = (SmvcState) stateCombo.getSelectedItem();
controller.setModelState(state);
});
JPanel comboPanel = new JPanel();
comboPanel.add(stateCombo);
cardPanel.add(new IntroPanel(), SmvcState.INTRO.toString());
cardPanel.add(new MainPanel(), SmvcState.MAIN.toString());
cardPanel.add(new MenuPanel(), SmvcState.MENU.toString());
mainPanel.setLayout(new BorderLayout());
mainPanel.add(cardPanel, BorderLayout.CENTER);
mainPanel.add(comboPanel, BorderLayout.PAGE_END);
}
public PropertyChangeListener getModelListener() {
return modelListener;
}
public void setController(SmvcController controller) {
this.controller = controller;
}
public void setVisible(boolean b) {
JFrame frame = new JFrame("Simple MVC");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (SmvcModel.STATE.equals(evt.getPropertyName())) {
SmvcState state = (SmvcState) evt.getNewValue();
cardLayout.show(cardPanel, state.toString());
}
}
}
private class IntroPanel extends JPanel {
public IntroPanel() {
setPreferredSize(new Dimension(400, 300));
setLayout(new GridBagLayout());
add(new JLabel(SmvcState.INTRO.toString()), SwingConstants.CENTER);
setBorder(BorderFactory.createTitledBorder(SmvcState.INTRO.toString()));
}
}
private class MainPanel extends JPanel {
public MainPanel() {
setPreferredSize(new Dimension(400, 300));
setLayout(new GridBagLayout());
add(new JLabel(SmvcState.MAIN.toString()), SwingConstants.CENTER);
setBorder(BorderFactory.createTitledBorder(SmvcState.MAIN.toString()));
}
}
private class MenuPanel extends JPanel {
public MenuPanel() {
setPreferredSize(new Dimension(400, 300));
setLayout(new GridBagLayout());
add(new JLabel(SmvcState.MENU.toString()), SwingConstants.CENTER);
setBorder(BorderFactory.createTitledBorder(SmvcState.MENU.toString()));
}
}
}
class SmvcController {
private SmvcView view;
private SmvcModel model;
public SmvcController(SmvcView view, SmvcModel model) {
this.view = view;
this.model = model;
view.setController(this);
model.addPropertyChangeListener(view.getModelListener());
}
public void setModelState(SmvcState state) {
model.setState(state);
}
public SmvcView getView() {
return view;
}
public SmvcModel getModel() {
return model;
}
}
class SmvcModel {
public static final String STATE = "state";
private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
private SmvcState state = SmvcState.INTRO;
public void addPropertyChangeListener(PropertyChangeListener modelListener) {
support.addPropertyChangeListener(modelListener);
}
public SmvcState getState() {
return state;
}
// notify listeners whenever state is changed
public void setState(SmvcState state) {
SmvcState oldValue = this.state;
SmvcState newValue = state;
this.state = state;
support.firePropertyChange(STATE, oldValue, newValue);
}
}
enum SmvcState {
INTRO("Intro"), MENU("Menu"), MAIN("Main");
private String text;
private SmvcState(String text) {
this.text = text;
}
public String getText() {
return text;
}
}