【问题标题】:Problems of checkName() and storing user input to ArrayList and boolean[]checkName() 和将用户输入存储到 ArrayList 和 boolean[] 的问题
【发布时间】:2013-11-02 06:34:55
【问题描述】:

这里我有一个 GUI 窗口,它基本上要求用户选择一个 JRadioButton 并在 JTextField 中输入一些内容,然后选择确认/取消。

这是一个我们必须制作 UML-to-Java 文本文件的项目。用户将输入类信息并选择 UML 关系,该程序必须在 JTextField 上打印出 Java clsas 文本。就像在 eclipse 中创建一个新类一样。

我想要做的是创建一个 boolean[] 来存储一个布尔数组,当用户选择 JRadioButton_A 时它将存储 true,而当用户选择 JRadioButton_B 时它将存储 false。我还想要在 JTextField 中输入的内容由 checkName() 进行检查,如果方法返回 false,则字符串将存储在 ArrayList 中。

下面是我的代码 - getName() 方法和 boolean[] 用于存储真假存在一些问题。当用户需要再次输入名称时,它会将丢弃的 sting/boolean 保存到数组中。 (对不起我的英语不好!)有没有更好的方法来制作这个程序?我觉得我把事情复杂化了,应该有更简单的方法。

这是要求用户输入班级信息的 UI 内容。用户必须选择 public/private 然后输入类名和 JTextField

private class Handler implements ActionListener{
    public void actionPerformed(ActionEvent event){
        String name = inputClassName.getText();
        classObject.addName(name);
        while (classObject.checkName(name) == true){
            JOptionPane.showMessageDialog(null, "Class name invalid. " +
                    "\nEntered name should not contain java keywords or equal to other existing names. " +
                    "\nPlease try again."); // doesn't work
            name = inputClassName.getText();
            classObject.addName(name);
        }// end if
        JOptionPane.showMessageDialog(null, "Class saved."); // doesn't work
        name = inputClassName.getText();
        classObject.addName(name);

    }// end actionPerformed()
}// end Handler class

private class Handler2 implements ActionListener{
    public void actionPerformed(ActionEvent event){
        boolean b = true;
        b = classObject.setPP();
        }
    }

private class Handler3 implements ActionListener{
    public void actionPerformed(ActionEvent event){
        boolean b = false;
        b = classObject.setPP();
        }
    }

这是将输入存储到 ArrayList 和 boolean[] 的方法

Scanner input = new Scanner(System.in);
JavaKeywords keyObject = new JavaKeywords();

private ArrayList<String> className = new ArrayList<String>();
private String name = new String();
private int size = className.size();
private Boolean[] bArray = new Boolean[size];


public boolean checkName(String name){
    boolean check = true;
    for (int i=0; i<=size; i++){
        if (keyObject.containsKeyword(className.get(i)) || name.equals(className.get(i))){

            boolean o = false;
            check = o;
        }// end if
    }// end for
    return check;
}// end checkName
    
public boolean setPP(){
    boolean b = true;
    return b;
}

public void addPP(Boolean[] bArray){
    this.bArray = bArray;
    for (int i=0; i>=size; i++){
        bArray[i] = setPP();
    }
}// add a Array of boolean. for className[i], its class type = item[i] in bArray. 
             // public = true, private = false
public String getPublicPrivate(){
    String p = "";
    for (int i =0; i<=size; i++){
        if(bArray[i]=true)
            p = "public";
        else
            p = "private";
    }
    return p;
}

已解决

解决方案:将string classNameboolean isPrivate 存储在一个类中并将该类变成一个ArrayList 可以让我免于麻烦。但是后来我遇到了另一个问题,那就是checkName() 在我更改代码后不起作用。 这是ActionListener

private class Handler implements ActionListener{
    public void actionPerformed(ActionEvent event){
        
        VirtualClass virtualObject = new VirtualClass();
        classObject.addClass(virtualObject);
        String name = inputClassName.getText();
        virtualObject.className = name;
        
        if (classObject.checkName(name) == false){
            JOptionPane.showMessageDialog(null, "Class name invalid. " +
                    "\nEntered name should not contain java keywords or equal to other existing names. " +
                    "\nPlease try again."); // Always return "invalid" message 
        } else {
            JOptionPane.showMessageDialog(null, "Class saved."); 
            name = inputClassName.getText();
            virtualObject.className = name;
        }
        
        if (event.getSource() == publicButton) {
            virtualObject.isPrivate = false;
        } else if (event.getSource() == privateButton) {
            virtualObject.isPrivate = true;
        }

    }// end actionPerformed()

这里是checkName() 方法

public boolean checkName(String name){
    boolean check = true;
    for (int i=0; i<=size; i++){
        if (keyObject.containsKeyword(classes.get(i).className) || name.equals(classes.get(i).className)){
            boolean o = false;
            check = o;
        }// end if
    }// end for
    return check;
}// end checkName

对于checkName() 中的containsKeyword(),我使用了@MrLore 的How to check if the class name is valid? 中的JavaKeywords 类。

【问题讨论】:

  • 发布相关代码而不是完整程序。
  • 我想我不明白数组的实际用途。如果您唯一的参数是公共或私有的两种状态,为什么不将其标记为公共的单个布尔值?然后,如果 public 为 false,您可以假设它是私有的。此外,我不完全理解您的获取/设置的目的。看起来你只需要一个像 setPP(boolean p) { public = p; } 这样的设置器。
  • 难波里 - 已编辑。 Radiodef - 谢谢!我只是觉得我一直在使程序复杂化,但我想不出更聪明的方法。我想我只是愚蠢......
  • 我猜我用的是数组,因为这个程序允许用户创建多个类,所以布尔值是指类类型 public/private 需要与 className 有链接。所以如果它是一个数组,我可以使用索引来查找类的类类型......如果这有意义
  • 如果您需要两个以上的状态或想要更具体地表示状态,您可以随时使用枚举。无论哪种方式,您都希望单个变量代表多个状态。作为旁注,您可以使用单个 ActionListener 并评估源以简化类似的内容:if (e.getSource() == radioButton1) {} else if (e.getSource() == radioButton2) {}.

标签: java swing user-interface arraylist


【解决方案1】:

我可能会做的是创建一个简单的类来表示您的字段,这样您就不必使用多个列表了。

public class VirtualClass {
    public boolean isPrivate;
    public String className = "Object";
}

ArrayList<VirtualClass> classes = new ArrayList<VirtualClass>(0);

public void addClass(VirtualClass clazz) {
    classes.add(clazz);
}

否则,您将不得不创建第二个某种类型的列表来保存公共/私有。您只需要并行更改它们。

// in actionPerformed

ClassObject.VirtualClass clazz = new ClassObject.VirtualClass();

clazz.isPrivate = rbPrivate.isSelected();
clazz.className = tfClassName.getText();

classObject.addClass(clazz);

并且忽略单选按钮上的侦听,因为从技术上讲,在您将类添加到列表之前,您不需要它们的状态。

要稍后访问这些字段,您只需要

for (VirtualClass clazz : classes) {
    System.out.println((clazz.isPrivate ? "private" : "public") + " " + clazz.className);
}

// or something like

for (int i = 0; i < classes.size(); i++) {
    System.out.println(classes.get(i).className + ":");
    if (classes.get(i).isPrivate) {
        System.out.println(" private");
    } else {
        System.out.println(" public");
    }
}

【讨论】:

  • 谢谢。你的 cmets 很有帮助。我已经摆脱了 checkName() 问题!但我仍然无法弄清楚如何连接“isPrivate”和“clazz”类名,以便程序最终可以打印出“public/private className”。
  • 在我的示例中,引用 clazz 只是被丢弃了。对象引用保存在列表中,您可以在以后随时访问它们。我添加了一个基本迭代的快速示例。
  • 我想请教您的AddClass() 方法,有一个VirtualClass 类型的参数clazz。每次用户有新输入时我都必须创建一个新的对象名称吗?
  • addClass 方法进入您的类中,无论 classObject 是什么,无论您保存列表。在所有这些情况下,引用 clazz 只是您用来传递对象并将其添加到 ArrayList 的临时引用。 Java 是对象的“按引用传递”,这意味着当您将对象作为参数传递给方法时,只有引用(在其他语言如 C++ 中称为指针)被传递给方法。对象本身不会被复制。所有的引用都指向内存中使用第一个 new VirtualClass() 创建的同一个对象。
  • 我想尝试更直接地回答您的问题,是的,您必须创建一个新对象。每当您的用户提交新条目时,您将在该方法中创建一个新对象并将其提交以添加到列表中。当方法返回时,您在方法内创建的 reference 将被丢弃,但当您将其添加到列表时,该对象将继续存在,因为仍然存在对它的引用(列表中的那个)。
【解决方案2】:

我并不完全相信您的整体方法。我认为“应该”/“可能”发生的是,用户输入您询问的所有信息,他们点击“接受”,您验证用户输入的信息,如果正确,您创建一个新对象代表根据需要输入此输入的结果。

我个人会避免使用布尔数组,或者至少以不同的方式公开它们。我遇到的主要问题是保持头脑清醒,0 的元素实际上是什么意思?

相反,我会在 ClassName 类上提供 getter/setter,它允许我设置/获取特定属性。当然,您可以在内部将值保存在数组中,但使用该类的任何人都不需要知道您如何存储这些值。

您的支票名称Handler 的问题在于您使用while-loop 阻塞了事件调度线程

这将阻止你的程序响应用户输入(和绘画本​​身)

        while (classObject.checkName(name) == true){
            JOptionPane.showMessageDialog(null, "Class name invalid. " +
                    "\nEntered name should not contain java keywords or equal to other existing names. " +
                    "\nPlease try again."); // doesn't work
            name = inputClassName.getText();
            classObject.addName(name);
        }// end if

Swing 是一个单线程框架,这意味着对 UI 的所有交互和更改都应在 EDT 的上下文中执行。同样,任何阻止或阻止该线程处理事件队列的东西都会阻止它响应新事件,包括重绘请求,从而使您的程序挂起

相反,您应该简单地检查 if-else 语句中的名称。如果有效,则创建新的ClassName 对象,如果无效,则显示一条消息并让方法退出。

查看Concurrency in Swing了解更多详情

【讨论】:

  • 这是正确的,我没有注意到。 while 循环将无限地重新评估自身并冻结程序,因为在事件中意味着它没有机会编辑文本。更好的程序是if (classObject.checkName(name)) { showMessageDialog(...); return; },然后在下次尝试进入时重新评估。
  • 谢谢。没有意识到while循环问题。而且我认为您的方法也是一种更好的方法。如果我为每组类名和类类型创建一个新对象,是否应该创建一个 ArrayList 来存储所有创建的对象?但是会不会更复杂,因为我必须调用每个对象,然后在需要打印结果时使用里面的方法?
  • 查看我的答案,这是我认为@MadProgrammer 也建议的实现。除非字段是私有的,否则您不需要显式使用 setter 和 getter。如果它们是公开的,您可以直接访问它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-22
  • 2014-11-28
相关资源
最近更新 更多