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

Така. Направих заявка. Той има mainFrame, който създава два панела, единият съдържа моите подобни на съветника бутони (напр. Next, Previous) и един cardLayout, който ми позволява да отида до следващия или предишния панел, който декларирам в mainFrame. Като имам интерфейс, Verifiable, мога да отменя всеки клас прозорец с функция isDataValid(), която решава дали бутоните next и prev трябва да извикват функции за обръщане на cardlayouts.

Изходният код може да се види по-долу:

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 (може и да греша), всичко, което пряко влияе върху поведението на самия изглед, трябва да остане в изгледа (като бутони за активиране / деактивиране). Всичко останало (функционални методи) трябва да се управлява от контролер.

Бих използвал Singleton Pattern. Имайте клас, наречен 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
Е, това ще работи ли с идеята ми, подобна на съветника, да имам същия външен GUI и да променям само съдържанието с моя cardPanel? Харесва ми простотата на начина, който имам сега, но знам, че в крайна сметка ще трябва да мигрирам към MVC, така че по-добре да го направя сега. Моят съветник трябва основно да функционира по следния начин: 1. Вход, последван от проверка, когато щракна напред. 2. Някакъв вход от потребителя чрез проверка, когато щракна напред. и т.н. Тъй като потребителят трябва да може да въвежда само някои данни и да щраква върху следващия и предишния, искам да го направя възможно най-прост. - person ; 22.03.2012
comment
kentcdodds: Благодаря ви за отзивите, наистина ги оценявам. Аз съм нов в GUI програмирането. (Имам ограничение на знаците в последния ми коментар) - person ; 22.03.2012
comment
Разбирам какво имаш предвид. Хм... Можете да опитате да имате гетери на компонентите, от които се нуждаете за JPanels и да обработвате всички щраквания върху бутони в главния изглед. Така че, имайте променлива, която следи кой панел е отворен и когато се щракне върху следващия бутон, извикайте гетърите за компонентите с информацията, от която се нуждаете, за да обработите въведеното от потребителя, след което изпратете тази информация за обработка към контролера. - person kentcdodds; 22.03.2012
comment
kentcdodds: Хм, добре. Имате ли нещо против да покажете някакъв изходен код какво имате предвид? Това все още ли ще работи със същия основен GUI в моя MainFrame (т.е. contentPane и трите бутона)? - person ; 22.03.2012
comment
Докато се опитвах да измисля добър пример, продължавам да стигам до заключението, че има много начини да се направи това. Така че мисля, че ще го оставя на вас. Ето някои предложения: 1. Имайте списък/карта с вашите карти (JPanels) и всеки път, когато бъде натиснат следващият бутон, преминавайте през списъка, за да намерите видимата карта и да правите каквото трябва с нея. 2. Имайте променлива, наречена currentCard, и я задавайте при всяко щракване върху бутона, за да знаете какво да правите следващия път, когато щракнете върху бутон. 3. Има повече начини. Просто правете това, което ви подхожда най-добре. Ако трябва да съм по-конкретен, уведомете ме. - person kentcdodds; 26.03.2012