0

我是 Swing 新手,我对 Java 的经验也很有限。我正在创建一个 GUI,但为了进入主屏幕,首先需要登录。我的课程结构是这样的:

类树的根:

public class master {

static mainwindow mainWindow;
static login loginScreen;

static JFrame frame;}

正确的用户名和密码的结果应该将面板从登录屏幕切换到主窗口。我的问题是,当在“登录”类中处理登录操作时,我无法访问我的 mainWindow 面板或框架,因为它们位于“更高”类中。

我希望我的要求很清楚,如果不是,我会用更多的代码和详细说明来编辑我的帖子。

4

2 回答 2

3

OO 中的重要概念之一是职责分离。

在您的情况下,Login组件不负责决定在成功登录后应该采取什么行动(您也可以争辩不成功)。

在这种情况下,您需要让登录组件通过某种方式通知相关方登录过程的状态。这最好使用观察者模式之类的东西来实现。

基本上,这意味着您有某种可以对更改做出反应的侦听器/回调。

在下面的示例中,我使用 aCardLayout作为切换视图的主要方法,但是您可以很容易地使用 aJDialog作为登录表单(就像 Hovercraft 所做的那样)并在处理登录后加载主框架成功地。

在此处输入图像描述

public class TestCardLogin {

    public static void main(String[] args) {
        new TestCardLogin();
    }

    public TestCardLogin() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel implements LoginListener {

        private MainPane mainPane;
        private LoginPane loginPane;

        public TestPane() {
            setLayout(new CardLayout());

            mainPane = new MainPane();
            loginPane = new LoginPane(this);

            add(mainPane, "MAIN");
            add(loginPane, "LOGIN");

            ((CardLayout) getLayout()).show(this, "LOGIN");

        }

        @Override
        public void loginSuccessful() {
            ((CardLayout) getLayout()).show(this, "MAIN");
        }

        @Override
        public void loginFailed() {
            JOptionPane.showMessageDialog(TestPane.this, "Login failed", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    public class MainPane extends JPanel {

        public MainPane() {
            JLabel label = new JLabel("Welcome!");
            Font font = label.getFont();
            label.setFont(font.deriveFont(Font.BOLD, 32));
            setLayout(new GridBagLayout());
            add(label);
        }
    }

    public class LoginPane extends JPanel {

        private JTextField user;
        private JPasswordField password;
        private JButton login;
        private LoginListener loginListener;

        public LoginPane(LoginListener listener) {
            this.loginListener = listener;
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(4, 4, 4, 4);
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.EAST;
            add(new JLabel("User name:"), gbc);
            gbc.gridy++;
            add(new JLabel("Password:"), gbc);

            gbc.gridx++;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.WEST;

            user = new JTextField(12);
            password = new JPasswordField(12);

            add(user, gbc);
            gbc.gridy++;
            add(password, gbc);

            login = new JButton("Login");

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.anchor = GridBagConstraints.CENTER;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(login, gbc);

            login.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    boolean accept = (boolean) (((int) Math.round(Math.random() * 1)) == 0 ? true : false);
                    if (accept) {
                        loginListener.loginSuccessful();
                    } else {
                        loginListener.loginFailed();
                    }
                }
            });

        }
    }

    public interface LoginListener {

        public void loginSuccessful();

        public void loginFailed();
    }
}
于 2013-03-04T23:33:27.037 回答
3

你不应该以你正在做的方式使用静态变量或方法,给方法和变量一个全局范围,因为这样做你失去了面向对象编程的许多优点。

你应该有一个主类,也许你可以称它为一个控制类,它运行所有东西并将引用传递到需要它的地方。通常我的登录窗口是模态对话框,例如 JDialog,它是主窗口的模态,主窗口是一个 JFrame。

例如,类似...

public class MasterControl {
   private MainView mainView = new MainView(this);
   private LoginView loginView = new LoginView(this);

   public MasterControl() {
      loginAndStart();
   }

   private void loginAndStart() {
      JFrame frame = new JFrame("MasterControl");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainView.getMainPanel());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);

      JDialog loginDialog = new JDialog(frame, "Log In", ModalityType.APPLICATION_MODAL);
      loginDialog.getContentPane().add(loginView.getMainPanel());
      loginDialog.pack();
      loginDialog.setLocationRelativeTo(frame);
      loginDialog.setVisible(true);

      // here extract info from loginView, ask model to validate login credentials
      // and then change main view.
   }
于 2013-03-04T23:25:56.793 回答