使用 java.awt 和 java.swing 的异常 java gui 垃圾邮件

unusual java gui spam using java.awt and java.swing

我正在按照 youtube 上的教程学习 java guis 并且我正在制作登录屏幕。 我正在测试登录按钮,方法是在控制台 w 中打印它,但我按下了。我正确地遵循了整个教程并尝试了各种方法。该代码正在向视频中显示的寡妇发送垃圾邮件。

link 到视频:https://hriday.tk/2022-01-09%2019-56-32.mkv

代码:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Login implements ActionListener{
    public Login() {
        JPanel panel = new JPanel();
        JFrame frame = new JFrame();
        JLabel Ulabel = new JLabel("UserName");
        JLabel Plabel = new JLabel("PassWord");
        JTextField Utext = new JTextField(20);
        JPasswordField Ptext = new JPasswordField(20);
        JButton login = new JButton("Login");
        JLabel success = new JLabel("");
        
        panel.setLayout(null);
        panel.add(Ulabel);
        panel.add(Utext);
        panel.add(Plabel);
        panel.add(Ptext);
        panel.add(login);
        panel.add(success);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setSize(350, 150);
        frame.setTitle("Login");
        frame.add(panel);
        
        Ulabel.setBounds(10, 10, 80, 25);
        Utext.setBounds(100, 10, 165, 25);
        Plabel.setBounds(10, 40, 80, 25);
        Ptext.setBounds(100, 40, 165, 25);
        login.setBounds(50, 70, 100, 25);
        success.setBounds(200, 70, 100, 25);

        login.addActionListener(new Login());
        }
    
    public static void main(String[] args){ new Login(); }
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("works");
    }
} ```

这导致了您的问题:

// imports

public class Login implements ActionListener {
    public Login() {
        
        // .... code removed

        login.addActionListener(new Login());  // **** here ****
    }
    
    // .....
}

您在登录构造函数中调用它,因此递归地创建新的登录对象,这意味着,每次调用登录构造函数时,它都会创建一个新的登录对象,该对象调用构造函数,该构造函数创建一个新的登录对象,哪个....好吧,你应该明白了。

改为:

login.addActionListener(this);

这里添加已经创建好的Login对象,this对象,添加到ActionListener中。


警告:

话虽如此,如果我没有提到使用空布局和 setBounds(...) 是不健康的,我会失职,因为这会导致 GUI 非常不灵活,虽然它们在一个平台上看起来不错但看起来很糟糕在大多数其他平台或屏幕分辨率上,很难更新和维护。相反,您需要研究和学习布局管理器,然后嵌套 JPanel,每个 JPanel 都使用自己的布局管理器来创建令人愉悦且复杂的 GUI,这些 GUI 在所有 OS 上看起来都不错。

因此,您最好了解和使用布局管理器。您可以在此处找到布局管理器教程:Layout Manager Tutorial, and you can find links to the Swing tutorials and to other Swing resources here: Swing Info.

...如果这是来自教程并且它建议使用空布局,那么放弃教程!

例如(使用 GridBagLayout):

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import javax.swing.*;

public class Login2 {
    private static final int GAP = 5;
    private JPanel mainPanel = new JPanel();
    private JTextField userNameField = new JTextField(20);
    private JPasswordField passwordField = new JPasswordField(20);
    private JButton loginButton = new JButton("Login");
    private JLabel successLabel = new JLabel(" ");
    
    public Login2() {       
        mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        mainPanel.setLayout(new GridBagLayout());
        
        mainPanel.add(new JLabel("UserName:"), createGBC(0, 0));
        mainPanel.add(userNameField, createGBC(1, 0));
        mainPanel.add(new JLabel("Password:"), createGBC(0, 1));
        mainPanel.add(passwordField, createGBC(1, 1));
        mainPanel.add(loginButton, createGBC(0, 2));
        mainPanel.add(successLabel, createGBC(1, 2));
        
        loginButton.addActionListener(e -> {
            successLabel.setText("Success");
            Window window = SwingUtilities.getWindowAncestor(mainPanel);
            window.dispose();
        });
    }
    
    public String getUserName() {
        return userNameField.getText();
    }
    
    public char[] getPassword() {
        return passwordField.getPassword();
    }
    
    // create constraints that help position components in the GridBagLayout-using container
    private GridBagConstraints createGBC(int x, int y) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.insets = new Insets(GAP, GAP, GAP, GAP);
        return gbc;     
    }
    
    public JPanel getMainPanel() {
        return mainPanel;
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Login2 login2 = new Login2();
            
            JDialog dialog = new JDialog(null, "Login", ModalityType.APPLICATION_MODAL);
            dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            
            dialog.add(login2.getMainPanel());
            dialog.pack();
            dialog.setLocationByPlatform(true);
            dialog.setVisible(true);
            
            System.out.println("User Name: " + login2.getUserName());
            System.out.println("Password:  " + new String(login2.getPassword()));
            
        });
    }
}