首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Swing 多視窗傳值:主視窗與登入視窗互動的標準模式實現

     編輯:程式設計綜合問答

場景需求

主視窗 (`MainFrame`) 點擊「登入」按鈕 → 顯示登入視窗 (`LoginDialog`) → 登入成功 → 將用戶資訊回傳主視窗並顯示 → 關閉登入視窗。

核心設計模式:回調介面 / 監聽器模式

登入視窗不直接操作主視窗元件,而是定義介面,主視窗實作介面並傳遞自身引用(`this`)。

完整代碼實現

1. 定義回調介面

public interface LoginListener {
    void onLoginSuccess(User user);  // 登入成功回調
    void onLoginCancel();            // 取消/關閉回調
}

2. 登入視窗

public class LoginDialog extends JDialog {
    private LoginListener listener;
    private JTextField tfUser;
    private JPasswordField pfPass;

    public LoginDialog(Frame owner, LoginListener listener) {
        super(owner, "用戶登入", true);  // true = 模態對話框,阻塞主視窗
        this.listener = listener;
        initUI();
        pack();
        setLocationRelativeTo(owner);
    }

    private void initUI() {
        // 佈局代碼省略...
        btnLogin.addActionListener(e -> attemptLogin());
        btnCancel.addActionListener(e -> { if (listener != null) listener.onLoginCancel(); dispose(); });
    }

    private void attemptLogin() {
        String user = tfUser.getText();
        String pass = new String(pfPass.getPassword());
        // 這裡應呼叫 Service 驗證,示例寫死
        if ("admin".equals(user) && "123456".equals(pass)) {
            User u = new User(user, "管理員");
            if (listener != null) listener.onLoginSuccess(u);
            dispose();
        } else {
            JOptionPane.showMessageDialog(this, "帳號或密碼錯誤");
        }
    }
}

3. 主視窗實作介面

public class MainFrame extends JFrame implements LoginListener {
    private JLabel lblStatus;

    public MainFrame() {
        initUI();
    }

    private void initUI() {
        lblStatus = new JLabel("未登入");
        JButton btnLogin = new JButton("登入");
        btnLogin.addActionListener(e -> new LoginDialog(this, this).setVisible(true));
        // 佈局...
    }

    @Override
    public void onLoginSuccess(User user) {
        lblStatus.setText("歡迎:" + user.getName() + " (" + user.getRole() + ")");
        // 可在此啟用需登入的功能按鈕等
    }

    @Override
    public void onLoginCancel() {
        // 使用者取消,可記錄日誌或不處理
    }
}

4. 用戶實體類

public class User {
    private String username;
    private String role;
    // 建構子、getter/setter 省略
}

關鍵設計點解析

進階擴展:異步登入 (SwingWorker)

private void attemptLogin() {
    String user = tfUser.getText();
    String pass = new String(pfPass.getPassword());
    btnLogin.setEnabled(false);
    new SwingWorker<User, Void>() {
        @Override protected User doInBackground() {
            return AuthService.login(user, pass);  // 耗時操作:資料庫、網路
        }
        @Override protected void done() {
            btnLogin.setEnabled(true);
            try {
                User u = get();
                if (u != null && listener != null) listener.onLoginSuccess(u);
                dispose();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(LoginDialog.this, "登入異常:" + ex.getMessage());
            }
        }
    }.execute();
}

總結

Java Swing 多視窗傳值標準模式:模態對話框 + 回調介面 + 傳遞 this。這樣實現低耦合、高復用、符合事件驅動架構。避免直接 `MainFrame.lblStatus.setText(...)` 硬編碼耦合,也避免非模態視窗導致的並發狀態混亂。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
要點說明
模態對話框`super(owner, title, true)` 阻塞主視窗互動,登入流程結束前無法操作主視窗
介面解耦`LoginDialog` 僅依賴 `LoginListener` 介面,不依賴 `MainFrame` 具體類,可復用於其他視窗
傳遞 this`new LoginDialog(this, this)` 第一個 `this` 是 owner(父視窗),第二個是 listener(回調實作)
線程安全Swing 事件派發執行緒 (EDT) 中執行,UI 更新安全;若驗證耗時,需 `SwingWorker` 異步處理