Gui 程序在 main 方法执行后停止,即使线程是非守护进程

Gui program stops after main method executes even if thread is non-daemon

我是 Java 的初学者,非常感谢任何提示。我正在制作一个简单的程序,它打开一个非常简单的登录 window,当你输入正确的密码 (Hello.123) 时,它应该执行第二个 class 打开另一个 window带有一个可以用箭头键移动的正方形。我尝试独立执行第二个 class 并且它工作正常,但是当我尝试将它作为主程序的一部分执行时,它不起作用。我认为这是因为第二个 class 作为守护线程执行,所以我尝试将其设为另一个 class 的子 class ,将线程设置为非守护进程,但是也没有用。有什么我想念的或者我做错了什么吗? (这里的代码使它成为非守护进程) Login.java 主包;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.Color;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.URL;
import main.PostFrameThr.PostFrame;
import main.PostFrameThr;

    public class Login {

public static void main(String[] args) throws IOException {
    
    System.out.println("Initializing main Method");
    
    Border border = BorderFactory.createLineBorder(Color.black,5);
    
    JFrame login = new JFrame();
    login.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    login.setTitle("Login");
    login.setResizable(false);
    login.setSize(600, 500);
    login.setLocation(350, 100);
    login.setVisible(true);
    
    URL url1 = Login.class.getResource("/resources/WindowLogo.png");
    URL url2 = Login.class.getResource("/resources/LoginLogo.png");
    
    ImageIcon logo = new ImageIcon(url1);
    ImageIcon loginico = new ImageIcon(url2);
    login.setIconImage(logo.getImage());
    login.getContentPane().setBackground(Color.gray);
    
    JButton loginButton = new JButton("Login");
    loginButton.setBounds(255, 210, 70, 60);
    login.add(loginButton);
    
    
    JTextField password = new JTextField();
    password.setBounds(190, 180, 200, 20);
    login.add(password);
    
    JLabel logintxt = new JLabel();
    logintxt.setText("Please Enter Your Password");
    logintxt.setIcon(loginico);
    logintxt.setForeground(Color.BLACK);
    logintxt.setSize(10, 10);
    logintxt.setHorizontalTextPosition(JLabel.CENTER);
    logintxt.setVerticalTextPosition(JLabel.TOP);
    logintxt.setFont(new Font("Plain",Font.PLAIN,20));
    logintxt.setBackground(Color.gray);
    logintxt.setOpaque(true);
    logintxt.setBorder(border);
    logintxt.setVerticalAlignment(JLabel.TOP);
    logintxt.setHorizontalAlignment(JLabel.CENTER);
    login.add(logintxt);
    
    SwingUtilities.updateComponentTreeUI(login);
    
    int lock = 1;
    
    if(lock==1) {
        System.out.println("Finished Loading Login Window Components");
        System.out.println("Initializing Login Method");
    }
    
    while(lock==1) {
    
    lock = lock + 1;
    lock = lock - 1;
        
    String passwordtext = password.getText();
    loginButton.addActionListener(new ActionListener() {
        @Override
         public void actionPerformed(ActionEvent e) {
         if(passwordtext.equals("Hello.123")) {
             System.out.println("Login Successfull!");
            // try {
            //Runtime.getRuntime().exec("calc.exe");
            //} catch (IOException e1) {
                // TODO Auto-generated catch block
                //e1.printStackTrace();
            //}
             new PostFrameThr();
             new PostFrame();
             login.dispatchEvent(new WindowEvent(login, WindowEvent.WINDOW_CLOSING));
            }
         }      
       });
      }
    }
  }

PostFrame.java

    package main;

    import java.awt.*;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import javax.swing.*;
    import java.lang.Thread;

    class PostFrameThr extends Thread {

static void thr() {
    PostFrameThr Thread = new PostFrameThr();
    Thread.setDaemon(false);
    Thread.start();
    new PostFrame();
}
    @SuppressWarnings("serial")
    public static class PostFrame extends JFrame implements KeyListener {
   
    int X = 155;
    int Y = 130;
    int size = 70;
    JLabel label;

PostFrame(){

    this.setTitle("Snake");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.setSize(400, 400);
    this.setLayout(null);
    this.addKeyListener(this);
    this.setLocationRelativeTo(null);
    
    label = new JLabel();
    label.setBounds(X, Y, size, size);
    label.setBackground(Color.black);
    label.setOpaque(true);
    label.setVisible(true);
    
    this.add(label);
    this.setVisible(true);
    
    SwingUtilities.updateComponentTreeUI(this);
    
}



@Override
public void keyPressed(KeyEvent e) {
    // TODO Auto-generated method stub
    switch(e.getKeyChar()) {
    case 'w' : label.setLocation(label.getX(), label.getY()-5);
      break;
    case 'a' : label.setLocation(label.getX()-5, label.getY());
      break;
    case 's' : label.setLocation(label.getX(), label.getY()+5);
      break;
    case 'd' : label.setLocation(label.getX()+5, label.getY());
    
    
    }
    
}

@Override
public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub
    
}

@Override
public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub
    
}


     }
    }

与大多数 GUI 框架一样,Swing 是事件驱动的。

做类似...

while (lock == 1) {

    lock = lock + 1;
    lock = lock - 1;

    String passwordtext = password.getText();

不仅不正确,而且 CPU 密集(更不用说在每次迭代中,您都会向按钮添加一个新的 ActionListener

相反,只需摆脱循环,当 ActionListener 被触发时,从 JTextField

中获取值
loginButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        String passwordtext = password.getText();
        if (passwordtext.equals("Hello.123")) {
            System.out.println("Login Successfull!");
            new PostFrameThr();
            new PostFrame();
            login.dispose();
        }
    }
});

您可能想花时间看看:

哦,SwingUtilities.updateComponentTreeUI(login); 并没有按照您认为的那样去做。相反,将 login.setVisible(true); 移动到 main 方法的末尾