【问题标题】:Redo cardlayout-application into MVC architecture在 MVC 架构中重做 cardlayout-application
【发布时间】:2012-03-21 14:56:50
【问题描述】:

所以。我已经申请了。它有一个 mainFrame,它创建了两个面板,一个包含我的类似向导的按钮(例如 Next、Previous)和一个 cardLayout,使我能够转到我在 mainFrame 中声明的下一个或上一个面板。通过拥有一个 Verifiable 接口,我能够覆盖每个窗口类的 isDataValid() 函数,该函数决定下一个和上一个按钮是否应该调用卡片布局翻转函数。

源码见下:

public class MainFrame {

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("Dimensions helper");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);

        final JPanel contentPane = new JPanel();
        contentPane.setLayout(new CardLayout(5, 5));

        Window1 win1 = new Window1();
        contentPane.add(win1);
        Window2 win2 = new Window2();
        contentPane.add(win2);
        Window3 win3 = new Window3();
        contentPane.add(win3);
        Window4 win4 = new Window4();
        contentPane.add(win4);
        Window5 win5 = new Window5();
        contentPane.add(win5);
        Window6 win6 = new Window6();
        contentPane.add(win6);

        JPanel buttonPanel = new JPanel(); 
        final JButton previousButton = new JButton("< PREVIOUS");
        previousButton.setEnabled(false);
        final JButton nextButton = new JButton("NEXT >");
        final JButton cancelButton = new JButton("CANCEL");
        buttonPanel.add(cancelButton);
        buttonPanel.add(previousButton);
        buttonPanel.add(nextButton);

        previousButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                CardLayout cardLayout = (CardLayout) contentPane.getLayout();
                cardLayout.previous(contentPane);
                Component[] contents = contentPane.getComponents();
                nextButton.setText("NEXT");
                for(Component component : contents) {
                    if(component instanceof Verifiable && component.isVisible()) {
                        Verifiable window = (Verifiable)component;
                        if(window.getIdentifier().equals("FIRST")) {
                            previousButton.setEnabled(false);
                        }
                        break;
                    }
                }
            }

        });

        nextButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                Verifiable verifiable = null;
                Component[] contents = contentPane.getComponents();
                for(Component component : contents) {
                    if(component.isVisible() && component instanceof Verifiable) {
                        verifiable = (Verifiable)component;
                    }
                }
                if(verifiable != null && verifiable.isDataValid()) {
                    CardLayout cardLayout = (CardLayout) contentPane.getLayout();
                    cardLayout.next(contentPane); 
                    previousButton.setEnabled(true);

                }
            }
        });



        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                System.exit(0);
            }

        });

        frame.add(contentPane);
        frame.add(buttonPanel, BorderLayout.PAGE_END);
        frame.setSize(400, 400);
        frame.setVisible(true);
    }



    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
} 

public class Window1 extends JPanel implements Verifiable {

    public static final String IDENTIFIER = "FIRST";

    JTextField txtUsername = new JTextField();
    JPasswordField txtPassword = new JPasswordField();

    Database db = new Database();

    public Window1() {
        init();
    }

    private void init() {
        JLabel lblUsername = new JLabel("Username:", JLabel.CENTER);
        lblUsername.setBounds(10, 91, 135, 77);
        txtUsername = new JTextField();
        txtUsername.setBounds(155, 116, 188, 27);

        JLabel lblPassword = new JLabel("Password:", JLabel.CENTER);
        lblPassword.setBounds(0, 163, 149, 77);
        txtPassword = new JPasswordField();
        txtPassword.setBounds(155, 188, 188, 27);
        setLayout(null);

        add(lblUsername);
        add(txtUsername);
        add(lblPassword);
        add(txtPassword);
        String title = "Log in";
        setBorder(BorderFactory.createTitledBorder(title));
    }

    @Override
    public boolean isDataValid() {
        String username = new String(txtUsername.getText());
        String password = new String(txtPassword.getPassword());


        try {
            Database conn = di.getDatabaseConnection(username, password);
            di.getTest(conn);
            return true;
            } catch (LoginFailedException e) {
                JOptionPane.showMessageDialog(this, "Something went wrong", 
                        "Error", JOptionPane.ERROR_MESSAGE);
                return false;
        }
    }

    @Override
    public String getIdentifier() {
        return IDENTIFIER;
    }
}

interface Verifiable {
    boolean isDataValid();
    String getIdentifier();
}

但是。我想将此应用程序重做为模型-视图-控制器架构,这意味着我不再在窗口类(即视图)中有任何验证代码。因此,我将旧的 Window 类分为 WinView 类 (Win1) 和接口 (Interface1) 和模型来验证数据。

public class Win1 extends JPanel implements Interface1 {

    JTextField txtUsername = new JTextField();
    JPasswordField txtPassword = new JPasswordField();


    public Win1() {
        JLabel lblUsername = new JLabel("Username:", JLabel.CENTER);
        txtUsername = new JTextField();
        JLabel lblPassword = new JLabel("Password:", JLabel.CENTER);
        txtPassword = new JPasswordField();

        setLayout(null);
        add(lblUsername);
        add(txtUsername);
        add(lblPassword);
        add(txtPassword);
        String title = "Log in";
        setBorder(BorderFactory.createTitledBorder(title)); 

    }

    @Override
    public String getUsername() {
        return txtUsername.getText();
    }

    @Override
    public String getPassword() {
        String password = new String(txtPassword.getPassword());
        return password;
    }

}

public interface Interface1 {
    String getUsername();
    String getPassword();
}


public class Model {

    Model() {

    }       
}

到目前为止,我的 MainFrame 看起来都一样。当我试图规划我的新架构时,我被卡住了。我应该如何绑定 MVC 架构?我对我的下一个和上一个按钮目前的工作方式感到非常满意,是否有可能像现在一样仍然使用它们?

【问题讨论】:

    标签: java swing model-view-controller user-interface cardlayout


    【解决方案1】:

    我想说的第一件事是,就我对 MVC 方法的理解(我可能是错的)而言,任何直接影响 View 本身行为方式的东西都应该保留在 View 中(例如启用/禁用按钮)。其他任何东西(功能方法)都应该由控制器处理。

    我会使用Singleton Pattern。有一个名为MainController 的类并在该类上使用单例模式。然后在您的MainView 中,有一个名为controllerMainController 实例的全局变量。然后在控制器中有一个isDataValid(String username, String password)的方法并调用boolean valid = controller.isDataValid(txtUsername.getText(), new String(txtPassword.getPassword()));。任何功能方法都可以完成同样的事情。我还要指出,控制器是唯一应该与数据库有任何连接以使 MVC 方法起作用的控制器。我希望这会有所帮助。

    【讨论】:

    • 嗯,这是否适用于我的类似向导的想法,即拥有相同的外部 GUI 并且只使用我的 cardPanel 更改内容?我喜欢我现在获得的简单方式,但我知道我最终需要迁移到 MVC,所以我现在最好这样做。我的向导基本上应该像这样运行: 1. 当我单击下一步时,登录后跟一个检查器。 2.当我点击下一步时,检查员的一些用户输入。等等。由于用户应该只能输入一些数据并单击下一个和上一个,我想让它尽可能简单。
    • kentcdodds:感谢您的反馈,非常感谢。我是 GUI 编程的新手。 (我上一条评论有字数限制)
    • 我明白你的意思。嗯...您可以尝试在 JPanel 所需的组件上安装 getter,并处理在主视图中单击的所有按钮。因此,有一个变量来跟踪哪个面板已启动,当单击下一个按钮时,使用处理用户输入所需的信息调用组件的 getter,然后将该信息发送到控制器。
    • kentcdodds:嗯,好的。您介意展示一些源代码吗?这仍然可以在我的 MainFrame 中使用相同的底层 GUI(即 contentPane 和三个按钮)吗?
    • 我一直在努力想出一个很好的例子,我不断得出结论,有很多方法可以做到这一点。所以我想我会把它留给你。以下是一些建议: 1. 制作一张卡片列表/地图(JPanels),每次按下下一个按钮时,循环遍历列表以找到可见卡片并使用它执行您需要的操作。 2. 有一个名为currentCard 的变量,并在每次单击按钮时设置它,以便您知道下次单击按钮时要做什么。 3.方法更多。只做最适合你的事。如果您需要我说得更具体一些,请告诉我。
    猜你喜欢
    • 2011-09-26
    • 1970-01-01
    • 2011-03-29
    • 2020-10-10
    • 2011-10-27
    • 2011-02-08
    • 1970-01-01
    • 2018-08-30
    相关资源
    最近更新 更多