首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Swing 圖形化登錄界面實戰:組件佈局、驗證碼繪製、事件處理全流程

     編輯:Java 相關知識

界面效果預覽

  • 標題區:Logo 圖片
  • 輸入區:用戶名、密碼(掩碼)、驗證碼輸入框 + 點擊刷新的圖形驗證碼面板
  • 按鈕區:登錄、退出、換一張驗證碼
  • 交互:回車觸發登錄、驗證碼不區分大小寫、失敗自動刷新

核心類結構


Login extends JFrame implements ActionListener
    - 組件字段: JLabel, JTextField, JPasswordField, JButton, PanelDemo
    - init(): 佈局初始化 (null 佈局 + setBounds)
    - actionPerformed(): 統一事件分發

PanelDemo extends Panel
    - paint(Graphics): 繪製驗證碼 (背景噪點 + 4位隨機字符)
    - 靜態字段 randomcaptcha 供主窗口驗證

關鍵代碼實現

1. 主窗口佈局 (絕對定位)


public class Login extends JFrame implements ActionListener {
    // 組件聲明...
    public Login() {
        setTitle("用戶登錄");
        setSize(400, 300);
        setLocationRelativeTo(null); // 居中
        setLayout(null); // 絕對佈局
        init();
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
    }

    void init() {
        // Logo
        JLabel logo = new JLabel(new ImageIcon("welcome.gif"));
        logo.setBounds(125, 10, 150, 70); add(logo);

        // 用戶名
        addLabelAndField("用戶名:", 90, 100, userNameInput = new JTextField(), 150, 100);

        // 密碼
        addLabelAndField("密碼:", 90, 130, passwordInput = new JPasswordField(), 150, 130);

        // 驗證碼區域
        JLabel capLabel = new JLabel("驗證碼:"); capLabel.setBounds(90, 160, 60, 40); add(capLabel);
        captchaInput = new JTextField(); captchaInput.setBounds(150, 160, 70, 20); add(captchaInput);
        
        // 圖形驗證碼面板
        PanelDemo capPanel = new PanelDemo(); 
        capPanel.setBounds(220, 160, 80, 20); add(capPanel);
        
        // 換一張按鈕
        JButton change = new JButton("換一張");
        change.setBounds(300, 160, 80, 20);
        change.setContentAreaFilled(false); change.setBorderPainted(false);
        change.addActionListener(this); add(change);

        // 登錄/退出按鈕
        addButton("登錄", "login.gif", 70, 200, KeyEvent.VK_L);
        addButton("退出", "exit.gif", 210, 200, KeyEvent.VK_X);
    }

    void addLabelAndField(String text, int lx, int ly, JTextField field, int fx, int fy) {
        JLabel l = new JLabel(text); l.setBounds(lx, ly, 60, 40); add(l);
        field.setBounds(fx, fy, 150, 20); field.addActionListener(this); add(field);
    }
    void addButton(String text, String icon, int x, int y, int mnemonic) {
        JButton b = new JButton(text, new ImageIcon(icon));
        b.setBounds(x, y, 120, 30); b.setMnemonic(mnemonic); b.addActionListener(this); add(b);
    }
}

2. 統一事件處理


public void actionPerformed(ActionEvent e) {
    Object src = e.getSource();
    if (src == changeBtn) { captchaPanel.repaint(); return; }
    if (src == logoutBtn) { 
        JOptionPane.showMessageDialog(this, "感謝使用,再見!"); 
        dispose(); return; 
    }
    if (src != loginBtn) return; // 只有登錄按鈕/回車進入驗證

    String user = userNameInput.getText();
    String pwd = new String(passwordInput.getPassword());
    String code = captchaInput.getText().trim().toUpperCase(); // 不區分大小寫

    if ("admin".equals(user) && "123456".equals(pwd)) {
        if (code.equals(PanelDemo.randomcaptcha)) {
            JOptionPane.showMessageDialog(this, "登錄成功!");
            // 這裡打開主系統窗口
        } else {
            JOptionPane.showMessageDialog(this, "驗證碼錯誤!");
            captchaPanel.repaint();
        }
    } else {
        JOptionPane.showMessageDialog(this, "用戶名或密碼錯誤!");
    }
}

3. 圖形驗證碼繪製 (PanelDemo)


class PanelDemo extends Panel {
    public void paint(Graphics g) {
        int w = 80, h = 20;
        g.setColor(Color.LIGHT_GRAY); g.fillRect(0, 0, w, h);
        g.setColor(Color.BLACK); g.drawRect(0, 0, w, h);

        Random rd = new Random();
        // 噪點
        for (int i=0; i<100; i++) {
            g.setColor(Color.RED);
            g.drawOval(rd.nextInt(w)-2, rd.nextInt(h)-2, 2, 2);
        }

        // 4 位隨機字符
        g.setFont(new Font("微軟雅黑", Font.BOLD, 18));
        g.setColor(Color.BLUE);
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<4; i++) sb.append(chars.charAt(rd.nextInt(chars.length()))).append(' ');
        g.drawString(sb.toString(), 0, 18);

        // 供驗證用 (去除空格)
        randomcaptcha = sb.toString().replaceAll(" ", "").toUpperCase();
    }
    public static String randomcaptcha;
}

進階優化建議

痛點優化方案
絕對佈局不適應 DPI/分辨率變化改用 GridBagLayout / MigLayout / FormLayout
驗證碼安全性低 (客戶端生成)後端生成、存 Redis、前端請求圖片 URL、限制嘗試次數
密碼明文傳輸/存儲HTTPS + BCrypt/Argon2 加鹽哈希
無「記住我」/自動登錄Token + Cookie (HttpOnly, Secure, SameSite)
圖片資源依賴文件系統打包進 JAR: getClass().getResource("/images/welcome.gif")
單線程阻塞 UI (網絡請求)SwingWorker 異步執行登錄邏輯

現代替代方案

  • JavaFX:FXML + CSS 分離、綁定屬性、動畫豐富、WebView 集成
  • Web 技術:Spring Boot + Vue/React 前後端分離、JWT 無狀態認證
  • 桌面端框架:TornadoFX (Kotlin/JavaFX)、Griffon (Groovy/Swing/JavaFX)

總結

這個 Swing 登錄界面雖簡單,但涵蓋了容器佈局、自定義繪製、事件監聽、組件狀態管理等 GUI 編程核心要素。理解其機制有助於維護舊系統、快速原型開發,也為遷移至現代技術棧打下基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved