Java 从SwingWorker实时更新GUI

Java 从SwingWorker实时更新GUI,java,swing,swingworker,event-dispatch-thread,invokelater,Java,Swing,Swingworker,Event Dispatch Thread,Invokelater,好的,这是我昨天问题的后续问题 考虑到SwingWorker

好的,这是我昨天问题的后续问题

考虑到
SwingWorker
的内部调用
SwingUtilities#invokeAndWait()
可能还可以,我想进一步问:在后台线程内部调用
SwingUtilities#invokeAndWait()
也可以吗?

另一个SSCCE用于说明:

public class NewClass extends javax.swing.JFrame {

    public NewClass() {
        jScrollPane1 = new javax.swing.JScrollPane();
        atable = new javax.swing.JTable();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        atable.setModel(new javax.swing.table.DefaultTableModel(
            new Object[][]{
                {null, null},
                {null, null},
                {null, null},
                {null, null}
            },
            new String[]{
                "Title 1", "Title 2"
            }
        ));
        jScrollPane1.setViewportView(atable);

        jButton1.setText("Go");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(jButton1)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 228, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1)
                .addContainerGap())
        );

        pack();
        setLocationByPlatform(true);
        setVisible(true);
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        new Task();
    }

    class Task extends javax.swing.SwingWorker<Void, Object[]> {

        DeterminateLoadingFrame dlf;

        public Task() {
            dlf = new DeterminateLoadingFrame();
            atable.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{},
                new String[]{
                    "Title 1", "Title 2"
                }
            ));
            dlf.setMaximum(1000);
            execute();
        }

        @Override
        protected void process(java.util.List<Object[]> chunks) {
            for (Object[] row : chunks) {
                ((javax.swing.table.DefaultTableModel) atable.getModel()).addRow(row);
            }
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (int i = 0; i < 1000; i++) {
                final int j = i;
                Object[] row = new Object[2];
                row[0] = "row " + i;
                row[1] = Math.round(Math.random() * 100);
                publish(row);
                javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        dlf.changeText("Processing " + j + " of " + 1000);
                        dlf.setValue(j);
                    }
                });
                Thread.sleep(100);

            }
            return null;

        }

        @Override
        protected void done() {
            if (!isCancelled()) {
                try {
                    get();
                } catch (java.util.concurrent.ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
            dlf.dispose();
        }

    }

    class DeterminateLoadingFrame extends javax.swing.JFrame {

        javax.swing.JLabel jLabel1;
        javax.swing.JProgressBar jProgressBar1;

        public DeterminateLoadingFrame() {

            jProgressBar1 = new javax.swing.JProgressBar();
            jLabel1 = new javax.swing.JLabel();

            setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
            setTitle("Loading");

            jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
            jLabel1.setText("Loading ...");

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE)
                        .addComponent(jProgressBar1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 182, Short.MAX_VALUE))
                    .addContainerGap())
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jLabel1)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            );

            pack();
            setAlwaysOnTop(true);
            setLocationRelativeTo(null);
            setVisible(true);
            setAlwaysOnTop(false);
        }

        public void changeText(String message) {
            this.jLabel1.setText(message);
            System.out.println(message);
        }

        public void setMaximum(int max) {
            jProgressBar1.setMaximum(max);
        }

        public void setValue(int n) {
            jProgressBar1.setValue(n);
        }

    }

    public static void main(String args[]) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new NewClass();
            }
        });
    }

    private javax.swing.JTable atable;
    private javax.swing.JButton jButton1;
    private javax.swing.JScrollPane jScrollPane1;
}
公共类NewClass扩展了javax.swing.JFrame{
公共类(){
jScrollPane1=newjavax.swing.JScrollPane();
atable=newjavax.swing.JTable();
jButton1=newjavax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setModel(新的javax.swing.table.DefaultTableModel(
新对象[][]{
{null,null},
{null,null},
{null,null},
{null,null}
},
新字符串[]{
“标题1”、“标题2”
}
));
jScrollPane1.setViewportView(atable);
jButton1.setText(“Go”);
jButton1.addActionListener(新java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent evt){
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout=newjavax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(布局);
layout.setHorizontalGroup(
createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1,javax.swing.GroupLayout.DEFAULT\u SIZE,380,Short.MAX\u值)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup()
.addGap(0,0,短.MAX_值)
.addComponent(jButton1)))
.addContainerGap())
);
layout.setVerticalGroup(
createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1,javax.swing.GroupLayout.DEFAULT\u SIZE,228,Short.MAX\u值)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1)
.addContainerGap())
);
包装();
setLocationByPlatform(真);
setVisible(真);
}
私有void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
新任务();
}
类任务扩展了javax.swing.SwingWorker{
确定帧dlf;
公共任务(){
dlf=新的确定框架();
setModel(新的javax.swing.table.DefaultTableModel(
新对象[][]{},
新字符串[]{
“标题1”、“标题2”
}
));
dlf.设定最大值(1000);
执行();
}
@凌驾
受保护的void进程(java.util.List块){
对于(对象[]行:块){
((javax.swing.table.DefaultTableModel)atable.getModel()).addRow(row);
}
}
@凌驾
受保护的Void doInBackground()引发异常{
对于(int i=0;i<1000;i++){
最终int j=i;
Object[]行=新对象[2];
行[0]=“行”+i;
行[1]=Math.round(Math.random()*100);
出版(世界其他地区);
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
dlf.changeText(“处理”+j+”或“+1000”);
dlf.设定值(j);
}
});
睡眠(100);
}
返回null;
}
@凌驾
受保护的void done(){
如果(!isCancelled()){
试一试{
get();
}catch(java.util.concurrent.ExecutionException | InterruptedException e){
e、 printStackTrace();
}
}
dlf.dispose();
}
}
类definiteLoadingFrame扩展了javax.swing.JFrame{
javax.swing.JLabel jLabel1;
javax.swing.jprogressbarjprogressbar1;
公共决策框架(){
jProgressBar1=newjavax.swing.JProgressBar();
jLabel1=newjavax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE\u ON\u CLOSE);
设置标题(“加载”);
jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel1.setText(“加载…”);
javax.swing.GroupLayout=newjavax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(布局);
layout.setHorizontalGroup(
createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.training)
.addComponent(jLabel1,javax.swing.GroupLayout.Alignment.LEADING,javax.swing.GroupLayout.DEFAULT\u SIZE,182,Short.MAX\u值)
.addComponent(jProgressBar1,javax.swing.GroupLayout.Alignment.LEADING,javax.swing.GroupLayout.DEFAULT\u SIZE,182,Short.MAX\u值))
.addContainerGap())
);
private static class Update {
    private int counter;
    private Object[] row;

    // constructor, getters omitted for brevity
}

...

class Task extends SwingWorker<Void, Update> {

    @Override
    protected Void doInBackground() throws Exception {
        for (int i = 0; i < 1000; i++) {
            Object[] row = new Object[2];
            row[0] = "row " + i;
            row[1] = Math.round(Math.random() * 100);
            publish(new Update(i, row);
            Thread.sleep(100);

        }
        return null;
    }

    @Override
    protected void process(java.util.List<Update> chunks) {
        for (Update update : chunks) {
            ((DefaultTableModel) atable.getModel()).addRow(update.getRow());   
        }
        int lastCounter = chunks.get(chunks.size() - 1).getCounter();
        dlf.changeText("Processing " + lastCounter + " of " + 1000);
        dlf.setValue(lastCounter);
    }
    ...
}
class Task extends javax.swing.SwingWorker<Void, Object[]> {

  public static final String ROW_COUNT = "row count";
  DeterminateLoadingFrame dlf;
  private int rowCount = 0;

  public Task() {
     dlf = new DeterminateLoadingFrame();  // and I would pass this in from the GUI
     atable.setModel(new javax.swing.table.DefaultTableModel(
           new Object[][] {}, new String[] { "Title 1", "Title 2" }));
     dlf.setMaximum(1000);
     // execute();  // I reserve this for the calling code.
  }

  public int getRowCount() {
     return rowCount;
  }

  public void setRowCount(int newValue) {
     int oldValue = this.rowCount;
     this.rowCount = newValue;

     firePropertyChange(ROW_COUNT, oldValue, newValue);
  }

  @Override
  protected void process(java.util.List<Object[]> chunks) {
     for (Object[] row : chunks) {
        ((javax.swing.table.DefaultTableModel) atable.getModel())
              .addRow(row);
     }
  }

  @Override
  protected Void doInBackground() throws Exception {
     for (int i = 0; i < 1000; i++) {
        final int j = i;
        Object[] row = new Object[2];
        row[0] = "row " + i;
        row[1] = Math.round(Math.random() * 100);
        publish(row);
        setRowCount(j);
        Thread.sleep(100);

     }
     return null;

  }

  // .....
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
  final Task task = new Task();
  task.addPropertyChangeListener(new PropertyChangeListener() {

     @Override
     public void propertyChange(PropertyChangeEvent evt) {
        if (Task.ROW_COUNT.equals(evt.getPropertyName())) {
           int rowCount = task.getRowCount();
           // do what you need with rowCount here
        }
     }
  });
  task.execute(); // again I usually call this here
}