Java Netbeans MVC模式下跨类关闭并切换JFrame的问题求助
问题原因
你当前代码的核心问题是LoginPage中静态实例lp和实际显示的窗口不是同一个对象:
- LoginPage类里定义了
public static LoginPage lp = new LoginPage();,这是一个独立的LoginPage实例 - 但main方法里是通过
new LoginPage().setVisible(true);创建了另一个完全不同的LoginPage实例并显示 - 所以控制器里调用
LoginPage.lp.dispose()时,关闭的是那个从未显示的静态实例,而你看到的登录窗口根本没被操作
解决方案
这里提供两种可行的修复方式,第二种更符合MVC设计原则:
方案一:复用静态实例(快速修复)
修改LoginPage的main方法,让它显示静态实例lp,而不是新建对象:
public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { // 改用已有的静态实例,而不是新建 LoginPage.lp.setVisible(true); } }); }
这样控制器里的LoginPage.lp.dispose()就能正确关闭显示的登录窗口了。
方案二:传递窗口引用(符合MVC解耦要求)
静态实例会导致视图和控制器强耦合,更规范的做法是把当前登录窗口的引用传给控制器:
- 修改LoginController的方法,添加LoginPage参数:
public static void collectUserData(String uname, String pword, LoginPage loginFrame) throws SQLException { Login user = new Login(); user.setUsername(uname); user.setPass(pword); checkDatabaseAndLogin(user, loginFrame); } public static void checkDatabaseAndLogin(Login test, LoginPage loginFrame) throws SQLException { JFrame rootPane; if (test.getUsername().equals("")||test.getPass().equals("")) { rootPane = new JFrame(); JOptionPane.showMessageDialog(rootPane, "Some fields are empty", "Error", 1); } else { try { Connection con = dbconnect.connect(); PreparedStatement pst = con.prepareStatement("select * from test where username=? and pass=?"); pst.setString(1, test.getUsername()); pst.setString(2, test.getPass()); ResultSet rs = pst.executeQuery(); if (rs.next()) { String un = rs.getString("username"); PatronPage pt = new PatronPage(un); pt.setVisible(true); // 关闭传入的登录窗口 loginFrame.dispose(); } else { rootPane = new JFrame(); JOptionPane.showMessageDialog(rootPane, "Username or Password do not match record", "Login error", 1); } } catch (Exception ex) { System.out.println(""+ex); } } }
- 修改LoginPage中按钮点击的调用代码,传入当前窗口的引用
this:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { String uname = jTextField1.getText(); String pword = jPasswordField1.getText(); try { // 传入当前LoginPage实例 LoginController.collectUserData(uname, pword, this); } catch (SQLException ex) { Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex); } }
这种方式让控制器不需要依赖视图的静态成员,更符合MVC中视图和控制器松耦合的设计思想。
内容的提问来源于stack exchange,提问作者Chizo
相关产品推荐
相关产品推荐

