Переделать приложение cardlayout в архитектуру MVC

Так. Я сделал заявку. У него есть mainFrame, который создает две панели, одна из которых содержит мои похожие на мастера кнопки (например, «Далее», «Предыдущий»), а другая — cardLayout, позволяющая мне перейти либо к следующей, либо к предыдущей панели, которую я объявляю в mainFrame. Имея интерфейс, проверяемый, я могу переопределить функцию 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();
}

Однако. Я хочу переделать это приложение в архитектуру Model-View-Controller, а это означает, что у меня больше нет кода проверки в классах Window (т.е. в представлениях). Поэтому я разделил старые классы 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? Я очень доволен тем, как мои кнопки «Далее» и «Предыдущий» работают на данный момент, можно ли как-то по-прежнему использовать их, как я сейчас?


person Community    schedule 21.03.2012    source источник


Ответы (1)


Первое, что я хочу сказать, насколько я понимаю методологию MVC (могу ошибаться), все, что напрямую влияет на поведение самого View, должно оставаться в View (вроде включения/отключения кнопок). Все остальное (функциональные методы) должно обрабатываться контроллером.

Я бы использовал шаблон Singleton. Имейте класс с именем MainController и используйте шаблон singleton в этом классе. Затем в вашем MainView есть глобальная переменная экземпляра MainController с именем controller. Затем в контроллере есть метод isDataValid(String username, String password) и вызовите boolean valid = controller.isDataValid(txtUsername.getText(), new String(txtPassword.getPassword()));. То же самое можно сделать любыми функциональными методами. Я также хотел бы отметить, что контроллеры — единственные, которые должны иметь какое-либо соединение с базой данных для работы методологии MVC. Надеюсь, это поможет.

person kentcdodds    schedule 22.03.2012
comment
Что ж, будет ли это работать с моей похожей на волшебство идеей иметь тот же внешний графический интерфейс и изменять содержимое только с помощью моей карты cardPanel? Мне нравится простота того, что я получил сейчас, но я знаю, что в конечном итоге мне нужно будет перейти на MVC, поэтому лучше сделать это сейчас. Мой мастер должен в основном работать следующим образом: 1. Войти в систему, а затем проверить, когда я нажимаю «Далее». 2. Некоторый ввод от пользователя чекером, когда я нажимаю «Далее». и т. д. Поскольку пользователь должен иметь возможность вводить только некоторые данные и нажимать «Далее» и «Предыдущий», я хочу сделать это как можно проще. - person ; 22.03.2012
comment
kentcdodds: Спасибо за ваш отзыв, я очень ценю его. Я новичок в программировании GUI. (Получил ограничение на количество символов в моем последнем комментарии) - person ; 22.03.2012
comment
Я понимаю, что вы имеете ввиду. Хм... Вы можете попытаться использовать геттеры для компонентов, необходимых для JPanels, и обрабатывать все нажатия кнопок в главном представлении. Итак, пусть переменная отслеживает, какая панель открыта, и при нажатии следующей кнопки вызывают геттеры для компонентов с информацией, необходимой для обработки пользовательского ввода, а затем отправляют эту информацию для обработки контроллеру. - person kentcdodds; 22.03.2012
comment
kentcdodds: Хм, хорошо. Не могли бы вы показать исходный код, что вы имеете в виду? Будет ли это работать с тем же базовым графическим интерфейсом в моем MainFrame (то есть с панелью содержимого и тремя кнопками)? - person ; 22.03.2012
comment
Пытаясь привести хороший пример, я все время прихожу к выводу, что есть много способов сделать это. Так что, думаю, я оставлю это вам. Вот несколько предложений: 1. Имейте список/карту ваших карточек (JPanels) и каждый раз, когда нажимается следующая кнопка, прокручивайте список, чтобы найти видимую карточку и делать с ней то, что вам нужно. 2. Создайте переменную с именем currentCard и устанавливайте ее каждый раз при нажатии кнопки, чтобы вы знали, что делать при следующем нажатии кнопки. 3. Способов больше. Просто делайте то, что вам больше всего подходит. Если вам нужно, чтобы я был более конкретным, дайте мне знать. - person kentcdodds; 26.03.2012