Java MVC-如何更改视图-JPanel [英] Java MVC - how to change view - JPanel

查看:125
本文介绍了Java MVC-如何更改视图-JPanel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建的目的是学习Java中的MVC.我读到很少有JFrames的Java应用程序是个坏主意,更好的解决方案是使用JPanel. JDialog也不能解决问题,因为那时我有太多这样的问题.我的MainFrame带有几个按钮,我的问题是-单击这些按钮之一后,如何在Frame上更改JPanels? 我知道如何更改视图是否为框架...

I am creating to learn MVC in Java. I read that Java app with few JFrames is bad idea and better solution is to use JPanel. JDialog also does not solve the problem, because then I have too many of them. I have the MainFrame with a few buttons and my question is - how to change JPanels on the Frame after click on one these buttons? I know how to change view if the View is Frame...

//ActionListener in the MainController
public void actionPerformed(ActionEvent e) {

                    TheView theView2 = new TheView(); //TheView extends JFrame
                    TheModel theModel2 = new TheModel();        
                    TheController theController = new TheController(theView2,theModel2);
                    theView.setVisible(false);
                    theView2.setVisible(true);
     }

..但是我不知道,如何只改变一帧上的面板? 我知道,我必须将侦听器添加到视图"中的按钮,然后在Controller中添加其余代码(如上述),但是我需要在Controller中更改视图吗?我应该在MainController还是MainFrameController中执行此操作? 以下是该应用程序的工作方式:

..but I have no idea, how to change only panels on the one frame? I know, that i have to add the listener to the button in the View and then in Controller add the rest of code (like above), but what do I need to change the view in the Controller? And should I do it in MainController or in the MainFrameController? Below is how to this app should work:

  1. 开始时会显示带有可见Panel1的MainFrame.
  2. 用户单击Button1.
  3. 同一台MainFrame显示的是Panel2.

以Panel3,4等等...

And so on with Panel3, 4...

感谢您的帮助.

是的,我知道CardLayout和TabbedPane,可以使用它们,但是我不知道如何在MVC中应用此解决方案. 我只需要回答随着JPanel的变化,这段代码看起来应该如何."而且应该在哪里.在MainController中?在MainFrameController中?

Yes, I know CardLayout and TabbedPane and I can use them, but I don't know how to apply this solution in MVC. "I just need answer how specifically should look like this piece of code with the change of the JPanel." And where should it be. In the MainController? In the MainFrameController?

推荐答案

我只需要回答随着JPanel的变化,这段代码看起来应该如何.我写道我可以在不使用MVC的情况下使用CardLayout,但是我不知道如何在MVC中进行操作...如何将其应用于MainFrame?

I just need answer how specifically should look like this piece of code with the change of the JPanel. I wrote that I can use CardLayout WITHOUT MVC, but I have no idea how to do it in MVC... How to apply it to the MainFrame?

您的控制器和模型代码不必在乎视图采用什么形式,无论它扩展JFrame,JPanel还是(都可能)扩展.大概在上面控件的actionPerformed方法中,视图,模型和控制器已经创建并适当地连接"了.在这个actionPerformed方法中,您要做的就是向模型发送命令以更改其状态.换句话说,控制器将在模型上调用将启动状态更改的方法.我通常有视图,然后通过侦听对模型的更改进行响应.

Your controller and model code shouldn't care what form the view takes, whether it extends JFrame, JPanel, or (probably best) neither. Presumably in your control's actionPerformed method above, the view, model and controller have already been created and appropriately "connected". In this actionPerformed method, all you'd do would be to send a command to the model to change its state. In other words, the controller would call a method on the model that would initiate a state change. I usually have the view then respond by listening for changes to the model.

这还没有完全连接",但是我想示例代码可能看起来像下面的代码.请注意,我更喜欢使用匿名内部类侦听器,这些侦听器是视图的一部分,并且它们本身会调用Controller方法:

This has not yet been fully "wired", but I imagine that sample code could look something like the code below. Note that I prefer to use anonymous inner class listeners that are part of the view and that themselves call Controller methods:

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<SmvcState> comboModel = new DefaultComboBoxModel<>(
            SmvcState.values());
    private JComboBox<SmvcState> 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;
    }
}

这篇关于Java MVC-如何更改视图-JPanel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆