从ActionListener中断开循环

时间:2017-11-22 17:33:38

标签: java swing jbutton actionlistener break

我正在开展一个学校项目,我正在开发一种游戏。在这个游戏中我要求用户登录,我面临一些困难。

以下是我的代码的相关部分:

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class User{
    int rank;
    String name;
    String pass;

User(){
    Scanner s = new Scanner(System.in);

    System.out.println("  Login\n1.New user\n2.Old user");
    int in = s.nextInt();

    for(;;){
        if(in == 1){
            //create new user
        }else if(in == 2){
            JFrame loginFrame = new JFrame();
            loginFrame.setVisible(true);
            loginFrame.setLayout(null);
            loginFrame.setSize(120+14,180+35);

            JLabel enterName = new JLabel("Enter Username:");
            enterName.setBounds(10,10,100,20);

            JTextField nameField = new JTextField();
            nameField.setBounds(120,10,130,20);

            JLabel enterPass = new JLabel("Enter Password:");
            enterPass.setBounds(10,40,100,20);

            JPasswordField passField = new JPasswordField();
            passField.setBounds(120,40,130,20);

            JButton hitEnter = new JButton("Login");
            hitEnter.setBounds(10,70,250,20);

            loginFrame.add(enterName);
            loginFrame.add(nameField);
            loginFrame.add(enterPass);
            loginFrame.add(passField);
            loginFrame.add(hitEnter);
            loginFrame.setSize(270+14,100+36);

            hitEnter.addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent enter){
                        name = nameField.getText();
                        pass = new String(passField.getText());

                        boolean validUser = checkUser(filename,name,pass);

                        if(validUser){
                            loginFrame.setVisible(false);
                            //some how break the for loop from here
                        }
                    }
                });

        }else{
            System.out.println("Invalid input.");
        }
    }
}

正如您所看到的,我需要以某种方式从actionlistener中退出for循环,但我不确定是否有任何方法可以执行此操作。

请帮帮我!!! 在此先感谢!!!

3 个答案:

答案 0 :(得分:1)

问题:

  • 首先,您在同一个程序中以错误的方式混合Swing和控制台代码。理解控制台(使用基于System.in的Scanner对象)是"线性"代码,程序员完全指导程序流程的代码,我们经常使用"阻塞"获取用户输入的代码,在输入输入之前完全阻止程序流的代码,这适用于while循环。另一方面,Swing GUI(和大多数GUI)代码主要是非线性事件驱动代码,用户可以更好地控制调用代码的代码,代码主要是避免阻塞代码流(具有异常)模态对话框)。
  • 如果你绝对必须将两者结合起来,那么你应该使用JFrame,因为显示JFrame不会暂停while循环,它会无休止地循环, 而不是一个好办法。相反,您需要使用Swing版本的阻止代码,模态对话框,使用JDialog或JOptionPane。这些将暂停while循环,允许更清晰和更线性的输入。
  • 无论您使用哪种,用户界面代码都不应该在User类中。此类应包含单个用户的状态(字段)和行为(方法),但同样不应包含UI代码。那属于其他地方;否则你最终会得到一个难以调试和增强的意大利面条代码。因此,请为您的用户提供包括姓名和排名在内的字段,为用户提供主要程序在希望用户执行操作时可以调用的方法,并将您的UI代码放在main方法中。
  • 使用Swing GUI来创建JPanel,然后将JPanel放在任何需要的位置,使代码更加灵活。例如,如果您这样做,那么您可以将JPanel放入JOptionPane,这意味着它将显示为模态对话框,阻止while循环,完全如您所愿。
  • 轻微狡辩:避免将字符串字段用于密码。这使得你的程序很容易被打破,并且不是一个好习惯。

所以,如果你绝对不得不混合使用Swing和控制台,我可以这样做:

首先是User.java类。同样,请仅关注用户状态和行为:

public class User {
    private int rank;
    private String name;
    private char[] pass; // ***** Don't store password as a String
    // ?? other fields if needed

    public User(String name, char[] pass) {
        this.name = name;
        this.pass = pass;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public int getRank() {
        return rank;
    }

    public String getName() {
        return name;
    }

    // again, if this were a real-world program, you wouldn't make password accessible
    public char[] getPass() {
        return pass;
    }

    // other User methods would go here

    @Override
    public String toString() {
        return "User [rank=" + rank + ", name=" + name + "]";
    }

    // you'll want to override equals(Object o) and hashCode() here
}

然后,您可以创建一个用于获取用户登录信息的JPanel。我想在显示这种类型的面板时使用GridBagLayout。例如:

// inports here....

@SuppressWarnings("serial")
public class GetUserInfo extends JPanel {
    private static final Insets INSETS = new Insets(4, 4, 4, 4);
    private JTextField nameField = new JTextField(10);
    private JPasswordField passField = new JPasswordField(10);

    public GetUserInfo() {
        // gridbaglayout works well for your needs
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = INSETS;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        add(new JLabel("Name:"), gbc);
        gbc.gridy = 1;
        add(new JLabel("Password:"), gbc);

        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.EAST;
        add(nameField, gbc);
        gbc.gridy = 1;
        add(passField, gbc);
    }

    // allow classes to query this JPanel for the user name 
    public String getName() {
        return nameField.getText();
    }

    // and password data
    public char[] getPass() {
        return passField.getPassword();
    }

}

然后在控制台程序中组合上述内容,在JOptionPane中显示此JPanel,因为这会创建一个模态对话框,该对话框会阻止程序流,直到处理完为止。你可以使用这样的代码:

    // user interface code can go here
    Scanner s = new Scanner(System.in);

    System.out.println("  Login\n1.New user\n2.Old user: ");
    int in = s.nextInt();
    s.nextLine();
    User user = null;  // hold our user object
    boolean inputNotOK = true; // keep looping until this is false
    GetUserInfo getUserInfo = new GetUserInfo();  // our JPanel for getting user sign in information
    if (in == 1) {
        // code to get a new user
    } else if (in == 2) {
        // code to sign in existing user
        while (inputNotOK) {
            String title = "Get User Name and Password";
            int optionType = JOptionPane.OK_CANCEL_OPTION;
            int msgType = JOptionPane.PLAIN_MESSAGE;
            int value = JOptionPane.showConfirmDialog(null, getUserInfo, title, optionType, msgType);
            if (value == JOptionPane.OK_OPTION) {
                // if the user presses "OK" on the dialog
                String name = getUserInfo.getName();
                char[] pass = getUserInfo.getPass();

                // validUser is a method that you have that checks if the user sign in is appropriate
                if (validUser(name, pass)) {
                    user = new User(name, pass);
                    System.out.println("new user: " + user);
                    inputNotOK = false;
                } else {
                    // show an error JOptionPane here to warn the user
                    // that their sign-on information was incorrect
                }
            }
        }
    }
    s.close();

// method that should check to see if user name and password are acceptable
private static boolean validUser(String name, char[] pass) {
    // TODO code to test if username and password are OK
    // TODO: change this to an actual test
    return true;
}   

使用这样的代码,如果您以后决定要删除所有控制台(扫描程序)代码,那么您可以,因为您现在已经拥有了可用于某个代码的JPanel桌面Swing GUI。

答案 1 :(得分:0)

[ { "text": "productone", "nodes": [ { "text": "level2", "nodes": [ { "text": "level3" }, { "text": "dog", "nodes": [ { "text": "bark" } ] }, { "text": "cat", "nodes": [ { "text": "meow" } ] } ] } ] }, { "text": "productwo", "nodes": [ { "text": "level2", "nodes": [ { "text": "level3", "nodes": [ { "text": "level4", "nodes": [ { "text": "level5" } ] } ] }, { "text": "level3a", "nodes": [ { "text": "level4a" } ] } ] }, { "text": "food", "nodes": [ { "text": "desserts", "nodes": [ { "text": "cookies" }, { "text": "cakes" }, { "text": "pies" } ] } ] } ] } ] 之前和之内添加一个布尔值。然后执行ActionListener语句来检查循环是否应该中断或继续。

if

答案 2 :(得分:0)

这里你去试一试

name 'apache'
maintainer 'xxxxx'
maintainer_email 'xxxxx'
license 'All Rights Reserved'
description 'Installs/Configures apache'
long_description 'Installs/Configures apache'
version '0.1.1'
chef_version '>= 12.1' if respond_to?(:chef_version)
depends 'apache'

#The `issues_url` points to the location where issues for this cookbook are
# tracked.  A `View Issues` link will be displayed on this cookbook's page 
when
# uploaded to a Supermarket.
#
# issues_url 'https://github.com/<insert_org_here>/apache/issues'

# The `source_url` points to the development repository for this cookbook.  
A
# `View Source` link will be displayed on this cookbook's page when uploaded 
to
# a Supermarket.
#
# source_url 'https://github.com/<insert_org_here>/apache'