【问题标题】:How to use JFileChooser in a JTable to select files and display data in the JTable如何在 JTable 中使用 JFileChooser 选择文件并在 JTable 中显示数据
【发布时间】:2020-06-16 20:53:27
【问题描述】:

我正在尝试实现 JFileChooser 以便能够从另一个程序制作的两个 .txt 文件中进行选择。我创建了一个相当简单的 JTable,它将根据我给它的路径从其中一个 .txt 文件中加载数据。但是我不知道如何使 JTable 实现 JFileChooser 以便能够选择任一文件并将数据显示在正确的单元格中。下面是 JTable 的代码和来自其中一个文件的一小部分数据

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class Maingui {

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            public void run() {
                new Maingui().createUI();
            }
        };

        EventQueue.invokeLater(r);
    }

    private void createUI() {

        try {
            JFrame frame = new JFrame();
            frame.setLayout(new BorderLayout());
            JTable table = new JTable();

            TableModel tableModel = new TableModel();
            BufferedReader file = new BufferedReader(new  FileReader("/Users/Will/Desktop/BenchmarkSortIterative.txt"));
            String line;
            file.readLine();

            List<Line> iterativeList = new ArrayList<Line>();
            while((line = file.readLine()) != null) {
                String splits[] = line.split(" ");
                String digits = line.replaceAll("[^0-9.]", "");
            }

            tableModel.setList(iterativeList);
            table.setModel(tableModel);

            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new JScrollPane(table));
            frame.setTitle("Benchmark Sorter");
            frame.pack();
            frame.setVisible(true);

        } catch(IOException ex) {}
    }

    class Line {

        private int size;
        private int avgCount;
        private int coefCount;
        private int avgTime;
        private int coefTime;

        public int getSize() {
            return size;
        }
        public void setSize(int size) {
            this.size = size;
        }
        public int getAvgCount() {
            return avgCount;
        }
        public void setAvgCount(int avgCount) {
            this.avgCount = avgCount;
        }
        public int getCoefCount() {
            return coefCount;
        }
        public void setCoefCount(int coefCount) {
            this.coefCount = coefCount;
        }
        public int getAvgTime() {
            return avgTime;
        }
        public void setAvgTime(int avgTime) {
            this.avgTime = avgTime;
        }
        public int getCoefTime() {
            return coefTime;
        }
        public void getCoefTime(int coefTime) {
            this.coefTime = coefTime;
        }
    }

    class TableModel extends AbstractTableModel {

        private List<Line> list = new ArrayList<Line>();
        private String[] columnNames = { "Size", "Avg Count", "Coef Count", "Avg Time", "Coef Time"};

        public void setList(List<Line> list) {
            this.list = list;
            fireTableDataChanged();
        }

        @Override
        public String getColumnName(int column) {
            return columnNames[column];
        }

        public int getRowCount() {
            return list.size();
        }

        public int getColumnCount() {
            return columnNames.length;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return list.get(rowIndex).getSize();
                default:
                    return null;
            }
        }
    }
}

来自 .txt 的数据

Data Set Size (n): 100
Iterative Selection Sort Results: 
Average Critical Operation Count: 1090
Standard Deviation of Count: 770
Average Execution Time: 10340

【问题讨论】:

    标签: java swing jtable jfilechooser


    【解决方案1】:

    声明:此答案最初由同一用户发布到 duplicate question,因此我将其重新发布在此处,以将所有内容保存在同一位置,以供将来的读者阅读。

    在开始解决主要问题之前,您有多个问题需要解决——您发布的代码甚至无法编译。

    这是您的代码,如下所示。你能发现问题吗?

    public void getCoefTime(int coefTime) {
        this.coefTime = coefTime;
    }
    

    它应该如下所示(你的编译器会提醒你这个问题):

    // this method should be a setter not a getter
    // your code called for setCoefTime(), but that method didn't exist
    public void setCoefTime(int coefTime) {
        this.coefTime = coefTime;
    }
    

    您的表模型缺少强制方法。每当您创建扩展接口的实现时,您都需要从该接口实现所有方法签名。在您的情况下,您缺少以下方法,并且您的编译器会再次警告您该问题:

    @Override
    public int getColumnCount()
    {
        return columnNames.length;
    }
    

    您的数据文件的组织方式不太理想。您似乎已将其编写为好像它的主要功能是向人提供信息,而不是向程序提供信息,因此即使您希望 JTable 水平显示,您也可以将这些漂亮的标签垂直而不是水平显示。

    代替

    Average Critical Operation Count: 30791
    Standard Deviation of Count: 32884
    Average Execution Time: 282750
    Standard Deviation of Time: 241038
    

    您应该有一个逗号分隔值 (CSV) 文件,例如

    trial 1,30791,32884,282750,241038
    trial 2,30791,32884,282750,241038
    trial 3,30791,32884,282750,241038
    trial 4,30791,32884,282750,241038
    

    您收到 ArrayIndexOutOfBoundsException 是因为您的代码正在读取该行

    Recursive Selection Sort Results:
    

    作为line1,当您致电line1[1] 时,那里什么都没有。你split在冒号上,但是冒号右边没有任何东西,所以split方法不用费心去创建一个新的token。

    摆脱所有漂亮的标题等,因为您只需要阅读这些行并在以后将它们扔掉——它们比无用更糟糕,因为当您的代码没有预料到它们的存在时,它们实际上会引入问题。

    现在,您似乎将文件读取代码建立在对文件读取方式的误解之上。不管你目前对文件阅读的理解是什么,忘记它,假装你以前从未听说过它。目标是逐行读取,将行分解成数据块(我们称它们为标记)并将它们打包成Line 对象,然后再移动到下一行——我们不是在读五行一次在这里。

    一旦你合理地组织输入数据,这种东西就不再需要了:

    String[] line1 = file.readLine().split(":");
    String[] line2 = file.readLine().split(":");
    String[] line3 = file.readLine().split(":");
    String[] line4 = file.readLine().split(":");
    String[] line5 = file.readLine().split(":");
    

    现在,你所要做的就是这样:

    while((line = bufferedReader.readLine()) != null)  
    {  
        // for purposes of clarity, we're changing the name of your Line object
        // in this example to TrialRecord
    
        String[] tokens = line.split(",");
        TrialRecord record = new TrialRecord();
        record.setSize( Integer.parseInt(tokens[0]));
        // the rest of your code...
    }  
    

    修复所有这些东西,您的表格将显示您的数据。

    【讨论】:

    • (1+) 是的,改变数据在文本文件中的存储方式是最好的解决方案。
    • 感谢您向我解释这个问题,我今天的大脑已经被炸了。但是我明白一切,直到record.setSize( Integer.parseInt(tokens[0]); 应该是一个开放的)。如果我在那里关闭它,它将编译但运行时它将在该特定行返回“AWT-EventQueue-0”java.lang.NumberFormatException。
    • 是的,对不起,我从你的代码中复制并粘贴了,但我似乎踩到了那个接近的括号。还有一件事要补充:当你做你的try/catch时,永远不要留下一个空的catch块。将ex.printStackTrace(); 放入其中,这样您就不会默默地使用错误消息。
    • 谢谢,我实际上添加了它。在 stackTrace 之后,它返回到同一行。这是因为它正在解析一个空字符串吗?
    • 会不会是因为它正在解析一个空字符串? - 我们不知道您文件中的数据是什么。如果您遵循此处给出的建议,那么第一个标记将是“试用 1”,它不是数字。在任何情况下,添加一个 System.out.println(…) 来显示 tokens[0] 的值。这是基本调试。
    【解决方案2】:

    JFileChooser 确实与问题无关。

    您需要开始学习如何使用文件中的数据创建您的List&lt;Line&gt; ArrayList,以便您可以调用setList() 方法。

    首先硬编码您要读取的文件名。然后创建一个 BufferedReader 来读取文件。

    那么对于文件中的每一行数据,你会:

    1. 解析数据以获取您的大小、计数和时间值
    2. 使用上面的值创建Line 对象的实例
    3. Line 对象添加到您的ArrayList

    当你读完文件后,你会在你的StudentTableModel 上调用setList(…) 方法。

    因此,首先使用硬编码的文件名让上述逻辑工作。然后,一旦成功,您就可以使用 JFileChooser 动态获取文件名。

    编辑:

    我不确定我是否正确解析数据

    告诉我们您发布的代码如何创建Line 对象。

    你为什么要在 " " 上执行 split()。在我看来,数据是用“:”分隔的。

    根据文件的格式,您需要分别解析 5 行数据,因此您的代码需要类似于:

    String[] line1 = file.readLine().split(":");
    String[] line2 = file.readLine().split(":");
    String[] line3 = file.readLine().split(":");
    String[] line4 = file.readLine().split(":");
    String[] line5 = file.readLine().split(":");
    
    Line line = new Line();
    line.setSize( Integer.parseInt(line1[1].trim()) );
    …
    line.setAvgTime( Integer.parseInt(line5[1].trim()) );
    iterativeList.add( line );
    tableModel.setList( iterativeList );
    

    【讨论】:

    • 我相信我做了适当的更改,但是我不确定我是否正确解析了数据。
    • 如果您能够创建一个Line 对象,那么它是正确的。我在您的代码中没有看到您创建 Line 对象的任何地方。真正的问题是你为什么还要使用 JTable。 JTable 用于以列格式显示多行数据。据我所知,您只有一行数据。
    • 样本数据为单节。我需要 JTable 以按十行显示 columnNames 中列出的列。
    • 我更改了代码以添加五行数据,但是如果我运行它,它将无法正常工作,因为数组列表超出了范围。
    • 样本数据是一个单独的部分。 - 我们怎么知道呢?如果我们没有所有信息,我们如何提出建议。那么显然我的建议是行不通的。您需要重构代码以一次读取 5 行数据,然后解析 5 行数据以创建您的 List 对象。 它不起作用,因为数组列表超出范围。 - 不知道这意味着什么。根据发布的代码,它与您读取数据的方法相同。我只能给你概念。由你来理解这个概念,然后编写代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 2014-05-06
    • 2013-12-18
    • 2017-06-07
    • 2020-10-02
    相关资源
    最近更新 更多