【问题标题】:Moving a method into SwingWorker将方法移动到 SwingWorker
【发布时间】:2014-08-10 20:29:27
【问题描述】:

我正在开发一个分析 DNA 的程序。该程序的主要工作是在一个方法中,接收某种文件类型,解析文件并将其转换为字符串,然后解析字符串以将其分割成段。然后,它在新的JFrame 上的JTable 中返回分析结果。

public  JTable readFile(File file) throws IOException{
    BufferedReader in = new BufferedReader(new FileReader(file));
    String line;
    String result = "";
    while((line=in.readLine())!=null) {
       if(!line.startsWith(">")) {
              result = result + line;
               }            
    }       

    Sequence sequence = new Sequence("Unspecified", result);
    ArrayList<Contig> contigs = sequence.getReadingFrames();

    String [] columnNames = {"Position", "Frame", "Sequence"};

     Object[][] data = new Object[contigs.size()][3];
     int j = 0;
    for (int i = 0; i <= contigs.size() && j < 3; i++){
        if (i == contigs.size()){
            j++;
            i = -1;
        }
        else if (j == 0){
            data[i][j] = Integer.toString(contigs.get(i).getStartPosition());   
        }
        else if (j == 1){
            data[i][j] = Integer.toString(contigs.get(i).getReadingFrame());
        }
        else if (j == 2){
            data[i][j] = contigs.get(i).getSequence();
        }
    }
    JTable seqTable = new JTable(data, columnNames);
    in.close();
    return seqTable;
}

我应该如何将其移至SwingWorker?我尝试了复制、粘贴和编辑,但整个过程只返回空结果。

【问题讨论】:

  • 谢谢你们的帮助!我使用了 My-Name-Is 的方法,因为它更容易集成到我当前的代码中。

标签: java swing file-io jtable swingworker


【解决方案1】:

我实际上有一个与“My-Name-Is”非常相似的答案,尽管我对其进行了很多简化以尝试显示执行流程,而不是迷失在细节中。

基本上,如果“整个事情只是返回空结果”,我想你可能搞砸了从后台线程到 GUI 线程的切换。仔细检查您的done() 方法,以确保您正确调用get()

还请记住,Swing 不是线程安全的,所有 GUI 组件(即您的 JTable)都必须在 EDT 上构建,在这种情况下,这意味着在 done() 方法内,而不是在后台线程内。

class TableBuilder extends SwingWorker<Object[][], Void> {
   private final String [] columnNames = {"Position", "Frame", "Sequence"};

   @Override
   public Object[][] doInBackground() throws Exception {
      // read your file, and build your data object...
      Object[][] data = new Object[someSize()][3];
      // then return it to the EDT ...
      return data;
   }
   @Override
   public void done() {
      // now on the EDT, build your GUI components, and 
      // update the GUI as needed.
      try {
         Object[][] data = get();
         JTable seqTable = new JTable(data, columnNames);
         // add your seqTable to the gui here...
      } catch (InterruptedException | ExecutionException ex) {
         // exit
      }
   }
}

【讨论】:

  • 不要在后台线程中创建 Swing 对象,异常 get() 返回对错误描述的引用,对 JTable 没有任何影响
【解决方案2】:

你至少有三个选择,你可以...

使用publish/process 填充预先存在的TableModel...

public class TableBuilder extends SwingWorker<Object[][], Object[]> {

    private DefaultTableModel tableModel;

    public TableBuilder(DefaultTableModel tableModel) {
        this.tableModel = tableModel;
    }

    @Override
    protected Object[][] doInBackground() throws Exception {
        try (BufferedReader in = new BufferedReader(new FileReader(file))) {
            String line;
            String result = "";
            while ((line = in.readLine()) != null) {
                if (!line.startsWith(">")) {
                    result = result + line;
                }
            }

            Sequence sequence = new Sequence("Unspecified", result);
            ArrayList<Contig> contigs = sequence.getReadingFrames();

            Object[][] data = new Object[contigs.size()][3];
            int j = 0;
            for (int i = 0; i <= contigs.size() && j < 3; i++) {
                if (i == contigs.size()) {
                    j++;
                    i = -1;
                } else if (j == 0) {
                    data[i][j] = Integer.toString(contigs.get(i).getStartPosition());
                } else if (j == 1) {
                    data[i][j] = Integer.toString(contigs.get(i).getReadingFrame());
                } else if (j == 2) {
                    data[i][j] = contigs.get(i).getSequence();
                }
                publish(data[i]);
            }
        }
        return data;
    }

    @Override
    protected void process(List<Object[]> chunks) {
        for (Object[] row : chunks) {
            tableModel.addRow(row);
        }
    }

}

doInBackground 方法中构建TableModel...

public class TableBuilder extends SwingWorker<TableModel, Void> {

    private JTable table;

    public TableBuilder(JTable table) {
        this.table = table;
    }

    @Override
    protected TableModel doInBackground() throws Exception {
        DefaultTableModel tableModel;
        try (BufferedReader in = new BufferedReader(new FileReader(file))) {
            String line;
            String result = "";
            while ((line = in.readLine()) != null) {
                if (!line.startsWith(">")) {
                    result = result + line;
                }
            }

            Sequence sequence = new Sequence("Unspecified", result);
            ArrayList<Contig> contigs = sequence.getReadingFrames();

            String[] columnNames = {"Position", "Frame", "Sequence"};

            Object[][] data = new Object[contigs.size()][3];
            int j = 0;
            for (int i = 0; i <= contigs.size() && j < 3; i++) {
                if (i == contigs.size()) {
                    j++;
                    i = -1;
                } else if (j == 0) {
                    data[i][j] = Integer.toString(contigs.get(i).getStartPosition());
                } else if (j == 1) {
                    data[i][j] = Integer.toString(contigs.get(i).getReadingFrame());
                } else if (j == 2) {
                    data[i][j] = contigs.get(i).getSequence();
                }
            }
            tableModel = new DefaultTableModel(data, columnNames);
        }
        return tableModel;
    }

    @Override
    protected void done() {
        try {
            TableModel model = get();
            if (model != null) {
                table.setModel(model);
            } else {
                // Handle possible null case...
            }
        } catch (InterruptedException | ExecutionException ex) {
            ex.printStackTrace();
        }
    }

}

返回构造TableModel所需的数据

public class TableBuilder extends SwingWorker<Object[][], Void> {

    private JTable table;

    public TableBuilder(JTable table) {
        this.table = table;
    }

    @Override
    protected Object[][] doInBackground() throws Exception {
        Object[][] data = null;
        try (BufferedReader in = new BufferedReader(new FileReader(file))) {
            String line;
            String result = "";
            while ((line = in.readLine()) != null) {
                if (!line.startsWith(">")) {
                    result = result + line;
                }
            }

            Sequence sequence = new Sequence("Unspecified", result);
            ArrayList<Contig> contigs = sequence.getReadingFrames();

            data = new Object[contigs.size()][3];
            int j = 0;
            for (int i = 0; i <= contigs.size() && j < 3; i++) {
                if (i == contigs.size()) {
                    j++;
                    i = -1;
                } else if (j == 0) {
                    data[i][j] = Integer.toString(contigs.get(i).getStartPosition());
                } else if (j == 1) {
                    data[i][j] = Integer.toString(contigs.get(i).getReadingFrame());
                } else if (j == 2) {
                    data[i][j] = contigs.get(i).getSequence();
                }
            }
        }
        return data;
    }

    @Override
    protected void done() {
        try {
            Object[][] rows = get();
            if (rows != null) {
                String[] columnNames = {"Position", "Frame", "Sequence"};
                TableModel tableModel = new DefaultTableModel(data, columnNames);
                table.setModel(model);
            } else {
                // Handle possible null case...
            }
        } catch (InterruptedException | ExecutionException ex) {
            ex.printStackTrace();
        }
    }

}

【讨论】:

  • +1 表示第一个代码示例,仍然不同意从 get() 获取任何内容
  • @mKorbel 对于第一个示例,我可以返回Void,但我想我将演示使用get 来获取Object[][] 行数据,但方向不同。 ..这都是上下文相关的,因此需要三个示例;) - 它还演示了可能的错误处理
  • 它还演示了可能的错误处理,在 Workers Thread 中创建 Swing 对象,我确定不是,嗯 :-) crocodile_free :-)
【解决方案3】:

试试这个。由于缺少依赖项,源未经过测试。您只需要找到一种方法来更新您的JTable。我建议使用TableModel 的实例创建CustomSwingWorker,然后在方法中更新它:protected void done()

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import javax.sound.midi.Sequence;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class CustomSwingWorker extends SwingWorker<TableModel, Void> {

    private File file;
    private JTable table;

    public CustomSwingWorker(final JTable table, final File file) {
        this.table = table;
        this.file = file;
    }

    @Override
    protected TableModel doInBackground() throws Exception {
        BufferedReader in = new BufferedReader(new FileReader(file));
        String line;
        String result = "";
        while ((line = in.readLine()) != null) {
            if (!line.startsWith(">")) {
                result = result + line;
            }
        }

        Sequence sequence = new Sequence("Unspecified", result);
        ArrayList<Contig> contigs = sequence.getReadingFrames();

        String [] columnNames = {"Position", "Frame", "Sequence"};

        Object[][] data = new Object[contigs.size()][3];
        int j = 0;
        for (int i = 0; i <= contigs.size() && j < 3; i++) {
            if (i == contigs.size()) {
                j++;
                i = -1;
            } else if (j == 0) {
                data[i][j] = Integer
                        .toString(contigs.get(i).getStartPosition());
            } else if (j == 1) {
                data[i][j] = Integer.toString(contigs.get(i).getReadingFrame());
            } else if (j == 2) {
                data[i][j] = contigs.get(i).getSequence();
            }
        }

        in.close();
        return new DefaultTableModel(data, columnNames);
    }

    protected void done() {
        try {
            this.table.setModel(this.get());
        } catch (Exception ignore) {
            // Simply ignore it ...
        }
    }
}

【讨论】:

  • 不要在后台线程中创建 Swing 对象,异常 get() 返回对错误描述的引用,对 JTable 没有任何影响
  • @mKorbel Swing Object ? DataObject 是自制类,还是你的意思。不一样?
  • JTable seqTable = new JTable(... 在 Workers Thread 中,所有 Swing 对象都将被初始化、设置,即“准备使用”...
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
相关资源
最近更新 更多