【问题标题】:Error populating Jlist with data from ArrayList使用 ArrayList 中的数据填充 Jlist 时出错
【发布时间】:2018-11-29 21:54:30
【问题描述】:

我正在制作一个程序,该程序将为从 Excel 表中提取的名称生成电子邮件。 我遇到的问题是,当我尝试将 Arraylist 数据传输到 Jlist ListModel 时,Gui 中没有显示任何内容。

我知道发布整个代码是多余的,但我宁愿过度分享,而不是让人们要求额外的部分来弄清楚发生了什么。问题完全在 Main 和 Window 类之间(非常确定)。

这是用于创建人员对象的人员类

public class person {
    private String fName, lName, serialNum, location, isDone;
// default constructor
public person() {
    fName = "default";
    lName = "default";
    serialNum = "0";
    location = "nowhere";
    isDone = "";
}

public person(String serialNum1, String fName1, String lName1, String 
location1, String isDone1) {
    this.fName = fName1;
    this.lName = lName1;
    this.serialNum = serialNum1;
    this.location = location1;
    this.isDone = isDone1;
}

// set first name
public void setFirst(String newFirst) {
    this.fName = newFirst;
}

// get first name
public String getFirst() {
    return fName;
}

////////
// set last name
public void setLast(String newLast) {
    this.lName = newLast;
}

// get last name
public String getLast() {
    return lName;
}

/////////
// set serial number
public void setSerial(String newSerial) {
    this.serialNum = newSerial;
}

// get serial number
public String getSerial() {
    return serialNum;
}

/////////
// set location
public void setLocation(String newLocation) {
    this.location = newLocation;
}

// get location
public String getLocation() {
    return location;
}

// set done
public void setDone(String newDone) {
    this.isDone = newDone;
}

// get done
public String getDone() {
    return isDone;
}

@Override
public String toString() {
    return ("serial: " + serialNum + " |  Name: " + fName + " " + lName + " |  Location: " + location + " |  Completed: "+isDone+ "\n");
}
public String label() {
    return " Name:                    " + fName + " " + lName + "                 done: "+isDone+ "\n";
}


///////////
// script///
///////////
public String printScript() {
    return "Hello " + fName + " " + lName + "\n\n" +

            "script"+

            "Serial #: " + serialNum + "\n\n" +

            "Location: " + location + "\n\n" +

            ;
}
}

主类读取 excel 文件并从中提取名称/数据。然后它将该数据放入 Arr a。 'a' 成功地将对象存储在 arraylist 中,但是当尝试使用 'w.fill(a);' 将 'a' 的内容移动到 GUI 时它没有做任何事情。 gui 显示一个空白的 jList。

public class Main extends JFrame {

/**
 * Launch the application.
 */
// connect program to desired excel file
private static final String fileName = "C:\\bigList.xlsx";
public static Arr a = new Arr();
public static Window w = new Window();

public static void main(String[] args) throws URISyntaxException {
    String subject = "title";
    String body = "See%20it";

    // temporary variables to store excel data for 1 row.
    // probably some way to make it more efficient than using nextCell. go by column
    // # or something
    String serial = "";
    String first = "";
    String last = "";
    String location = "";
    // could be changed to boolean
    String done = "";
    int jump;
    // create arraylist to store excel file

    try {

        // initialize reading of excel file
        FileInputStream excelFile = new FileInputStream(new File(fileName));

        // opens workbook for java to read
        Workbook workbook = new XSSFWorkbook(excelFile);

        // gets workbook sheet, usually 0, can be other values in case of 
multiple
        // sheets
        Sheet datatypeSheet = workbook.getSheetAt(0);

        // initialize iterator for new rows
        Iterator<Row> iterator = datatypeSheet.iterator();

        // while there is a row with data it will keep going
        while (iterator.hasNext()) {

            // increment var reset. stores iterator position
            jump = 0;

            // adds temp data to arraylist
            a.getList().add(new person(serial, first, last, location,done));

            // since only some columns of 'completed' are populated, the 'done' variable has
            // to be reset to null
            // otherwise the status will remain as yes, after the first yes, since that is
            // the only other variable state
            done = "";

            // initialize row iterator
            Row currentRow = iterator.next();

            // initialize cell iterator
            Iterator<Cell> cellIterator = currentRow.iterator();

            // while there is data in a cell, it will keep iterating to the right to the
            // next cell
            while (cellIterator.hasNext()) {

                // increments column/cell value
                jump++;

                // create cell object
                Cell currentCell = cellIterator.next();

                // if cell contains string & isnt null value, will jump to subgroup of if
                // statements
                if (currentCell.getCellType() == CellType.STRING && 
currentCell.getCellType() != null) {

                    // depending on position, store in corresponding temp value
                    // probably a better way to do this
                    // System.out.println(jump);

                    if (jump == 1) {
                        serial = currentCell.getStringCellValue();
                    }
                    if (jump == 2) {
                        first = currentCell.getStringCellValue();
                    }
                    if (jump == 3) {
                        last = currentCell.getStringCellValue();
                    }
                    if (jump == 4) {
                        location = currentCell.getStringCellValue();
                    }
                    if (jump == 5) {
                        done = currentCell.getStringCellValue();
                    }
                } else if (currentCell.getCellType() == CellType.NUMERIC) {
                    // no numeric values so nothing needed
                }

                // if cellIncrementer encounters empty cell it breaks loop and moves down to
                // next row
                else if (currentCell.getCellType() == null) {
                    break;
                }
            }

        }
        // removes column headers row from list
        a.getList().remove(0);
        a.getList().remove(0);

        // error catch messages
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    /////////////////////////////////////////
    System.out.println(a.getList());
    // ISSUE
    // 'a' arraylist in is not getting transferred to gui
    w.fill(a);
    w.run();

    /////////////////////////////////////////////
}

// create outlook email.
// Desktop.getDesktop().mail( new URI(
// "mailto:prrout@inautix.co.in?subject="+subject+"&body="+body) );

}

生成 gui 的窗口类

public class Window extends JFrame {

private JPanel contentPane;

/**
 * Launch the application.
 */

/**
 * Create the frame.
 */

DefaultListModel<person> listModel = new DefaultListModel<>();

public Window() {

    JList<person> list = new JList<person>(listModel);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);
    getContentPane().setLayout(new BorderLayout(0, 0));

    JButton button = new JButton("Generate Email");
    button.setFont(new Font("Tahoma", Font.PLAIN, 12));
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
        }
    });
    getContentPane().add(button, BorderLayout.SOUTH);
    JScrollPane scrollPane = new JScrollPane(list);
    getContentPane().add(scrollPane, BorderLayout.CENTER);

    JLabel lblSelectPeople = new JLabel("Select Person(s)");
    lblSelectPeople.setFont(new Font("Tahoma", Font.PLAIN, 12));
    lblSelectPeople.setHorizontalAlignment(SwingConstants.CENTER);
    scrollPane.setColumnHeaderView(lblSelectPeople);
}

// needs to be variable 'a' from Main class
public void fill(Arr a) {
    for (int i = 0; i < a.getList().size(); i++) {
        listModel.addElement(a.getList().get(i));
    }
}

public void run() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Window frame = new Window();

                frame.setVisible(true);
                frame.getContentPane().setSize(800, 400);
                frame.setBounds(200, 50, 630, 500);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}}

my arraylist class

public class Arr {
// create arraylist instance
ArrayList<person> arr = new ArrayList<person>();

// create getter unnecessary
public Arr() {
}

public ArrayList<person> getList() {
    return this.arr;
}}

【问题讨论】:

  • 您所问的问题涉及多个大型复杂类交互时发生的错误,您或我们难以解决的问题,因为我们没有可编译/可运行的,所以对我们来说更加困难代码,你做。我建议您应该做的第一件事是使用调试器来隔离问题。如果仍然卡住并且您需要我们的帮助,那么您需要创建并发布一个有效的 minimal reproducible example,发布一个 small 可编译和可运行的程序,适合此处在您的问题中,我们可以编译并直接为我们演示问题。
  • 好的,我已经浏览了这段代码,并且您正在创建多个 Window 变量。一个填充数据,另一个显示。检查你上面的代码——它应该只有new Window() 一次,你调用了两次,证明了我的意思。这是一个粗心的错误,但很常见。
  • ^谢谢。我在 Window 类中将“Window frame”变量切换为 static,并在 Main 类中删除了“Window w”并解决了它。我很欣赏这种洞察力。
  • 不建议这样做,因为这样做会失去 OOP 的所有好处,并且由于圈复杂度的增加而增加了错误的风险 - 查一下。
  • ^我想我找到了(正确的)修复它的方法。我将 Arraylist 实例放入一个单例类中,这样就解决了很多访问它的问题。

标签: java user-interface object arraylist jlist


【解决方案1】:

您正在创建多个 Window 变量,如果您在上面的代码中搜索 new Window(),这很容易证明。这应该出现一次,并且您将调用它两次。您调用fill(...) 并为其提供数据的一个窗口,您在run() 方法中创建的另一个窗口,您不要 调用fill(...) 而是显示它没有数据。解决方案:不要这样做。创建一个对象,填充并显示它。

我的 MCVE 证明了这一点:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;

public class Main extends JFrame {
    public static Arr a = new Arr();
    public static Window w = new Window();

    public static void main(String[] args) {

        // fill the gui with dummy data for our purposes without need of
        // outside excel libraries
        for (int i = 0; i < 20; i++) {
            String fName1 = "first name " + i;
            String lName1 = "last name " + i;
            a.getList().add(new Person(fName1, lName1));
        }
        a.getList().remove(0);
        a.getList().remove(0);
        System.out.println(a.getList());
        w.fill(a);
        w.run();
    }
}

class Window extends JFrame {
    private JPanel contentPane;
    DefaultListModel<Person> listModel = new DefaultListModel<>();

    public Window() {
        JList<Person> list = new JList<Person>(listModel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);
        getContentPane().setLayout(new BorderLayout(0, 0));
        JButton button = new JButton("Generate Email");
        button.setFont(new Font("Tahoma", Font.PLAIN, 12));
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            }
        });
        getContentPane().add(button, BorderLayout.SOUTH);
        JScrollPane scrollPane = new JScrollPane(list);
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        JLabel lblSelectPeople = new JLabel("Select Person(s)");
        lblSelectPeople.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lblSelectPeople.setHorizontalAlignment(SwingConstants.CENTER);
        scrollPane.setColumnHeaderView(lblSelectPeople);
    }

    public void fill(Arr a) {
        for (int i = 0; i < a.getList().size(); i++) {
            listModel.addElement(a.getList().get(i));
        }
    }

    public void run() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    // ******Don't create a new Window object!!!!!!!!!!!! **********

                    // Window frame = new Window();
                    // frame.setVisible(true);
                    // frame.getContentPane().setSize(800, 400);
                    // frame.setBounds(200, 50, 630, 500);

                    Window frame = Window.this;
                    frame.setVisible(true);
                    frame.getContentPane().setSize(800, 400);
                    frame.setBounds(200, 50, 630, 500);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

class Arr {
    ArrayList<Person> arr = new ArrayList<Person>();

    public ArrayList<Person> getList() {
        return this.arr;
    }
}

// Should be named Person, not person
class Person {
    private String fName, lName;

    public Person() {
        fName = "default";
        lName = "default";
    }

    public Person(String fName1, String lName1) {
        this.fName = fName1;
        this.lName = lName1;
    }

    public void setFirst(String newFirst) {
        this.fName = newFirst;
    }

    public String getFirst() {
        return fName;
    }

    public void setLast(String newLast) {
        this.lName = newLast;
    }

    public String getLast() {
        return lName;
    }

    @Override
    public String toString() {
        return (" |  Name: " + fName + " " + lName);
    }

    public String label() {
        return " Name:                    " + fName + " " + lName + "                 done: "
                + "\n";
    }

    public String printScript() {
        return "Hello " + fName + " " + lName + "\n\n";
    }
}

其他不相关的问题:

  • 避免设置大小/边界等,而是使用更简洁的方式设置大小,包括为 JList 提供可见的行数并在 JList 上调用 setPrototypeCellValue(...) 来设置其宽度
  • person 类重命名为Person。您的代码应遵循Java naming conventions - 变量名应全部以小写字母开头,而类名应以大写字母开头。学习这一点并遵循这一点将使我们能够更好地理解您的代码,并使您能够更好地理解其他人的代码。
  • 您的 Arr 类没有任何用处,而仅使用 ArrayList&lt;Person&gt; 对象就无法实现。摆脱这个类。
  • 您的个人数据最好显示在 JTable 而不是 JList 中。考虑使用 DefaultTableModel 和 JTable 代替您的 JList。
  • 避免创建扩展 JFrame 的类,因为这会迫使您创建和显示 JFrame,而通常需要更大的灵活性。事实上,我敢说您正在创建的窗口可能不是基本应用程序窗口,而是一个子窗口或“对话”窗口。如果是这样,最好在 JDialog 而不是 JFrame 中创建和显示数据。
  • 避免使用与核心 Java 类名冲突的类名,例如“Window”。使用更具体和更具描述性的东西。

【讨论】:

  • 感谢您的建议。我完全忽略了这一点。
猜你喜欢
  • 2012-01-14
  • 1970-01-01
  • 2014-08-30
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 2015-01-12
  • 2018-04-07
  • 1970-01-01
相关资源
最近更新 更多