动态地向JTable添加行 - 为什么它们一次出现? [英] Dynamically adding rows to JTable - Why do they appear at once?

查看:115
本文介绍了动态地向JTable添加行 - 为什么它们一次出现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在该示例中,我正在寻求向GUI添加一个表,然后向其中动态添加行(以显示进度)。我不明白的是为什么所有的行都会立刻出现。我的意思是,桌子的变化,不是吗?有人可以给我一个解释吗?

In the example, I'm seeking to add a table to my GUI and then dynamically add rows to it (to show the progress). What I don't understand is why all the rows are appearing at once. I mean, the the table's changing, isn't it? Can someone please give me an explanation?

import java.awt.Component;

public class Main {
  public static void main(String[] args) {
    // Show GUI
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        GUI gui = new GUI();
        gui.setVisible(true);

        DefaultTableModel model = new DefaultTableModel(
          new String[] { "Column 1", "Column 2" }, 0);
        JTable table = new JTable(model);

        gui.add(table);
        gui.validate();

        for (int i = 0; i < 10; i++) {
          System.out.println("Row " + i);
          model
            .addRow(new String[] { "Row", String.valueOf(i) });
          // model.fireTableDataChanged();

          try {
            Thread.sleep(250);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }

        }
      }
    });
  }
}

class GUI extends JFrame {
  private static final long serialVersionUID = 1L;

  public GUI() {
    setTitle("GUI");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 350, 100);
    setLocationRelativeTo(null);

    JPanel cp = new JPanel();
    cp.setBorder(new EmptyBorder(10, 10, 10, 10));
    setContentPane(cp);
  }
}


推荐答案

As由kleopatra和peeskillet指出,我最初的例子遭遇了一个愚蠢的错误。值得注意的是,peeskillet和我正在采用不同的方法。在我的示例中,列旨在表示可能花费未知时间且实际上可能失败的连接尝试(或多或少)(在这种情况下,只有在这种情况下,下一列才会起作用等等) )。因此,对我来说一次添加行是没有意义的(这可能是因为我的例子对peeskillet来说看起来很奇怪)。我已经使用SwingWorker解决了这个任务。正如kleopatra所指出的,还有另一个错误,现在已经修复了。这是我的代码:

As pointed out by kleopatra and peeskillet, my initial example suffered from a stupid mistake. It's worth noting that peeskillet and I were following different approaches, though. In my example, the columns meant to represent connection attempts (more or less) that can take an unknown amount of time and that can actually fail (in that case, and only in that case, the next column would come into play and so on). Therefore, it wouldn't have made sense for me to add the rows at once (which was probably what made my example look weird to peeskillet). I've solved the task using a SwingWorker. As pointed out by kleopatra, there was a another mistake, which is now fixed. Here's my code:

package SwingWorkerExampleCopy;

import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.BorderLayout;

public class SwingWorkerExampleCopy {
  public static void main(String[] args) {
    // Show GUI
    java.awt.EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        GUI gui = new GUI();

        DefaultTableModel tableModel = new DefaultTableModel();

        // Use a SwingWorker
        Worker worker = new Worker(tableModel);
        worker.execute();

        JTable table = new JTable(tableModel);
        table.setEnabled(false);
        // table.setTableHeader(null);

        JScrollPane scrollPane = new JScrollPane(table);
        gui.getContentPane()
          .add(scrollPane, BorderLayout.CENTER);

      }
    });
  }
}

class GUI extends JFrame {
  private static final long serialVersionUID = 1L;

  public GUI() {
    setTitle("GUI");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 350, 400);
    setLocationRelativeTo(null);
    setVisible(true);

    JPanel contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
    contentPane.setLayout(new BorderLayout(0, 0));

    setContentPane(contentPane);
  }
}

class Worker extends SwingWorker<DefaultTableModel, Object[]> {

  private final static int  numRows = 10;
  private final static int  numCols = 10;

  private DefaultTableModel model;

  Worker(DefaultTableModel model) {
    this.model = model;
    model.setColumnCount(numCols);
  }

  @Override
  protected DefaultTableModel doInBackground() throws Exception {
    // Add row
    for (int row = 0; row < numRows; row++) {
      // Build columns
      for (int col = 0; col < numCols; col++) {
        if (col == 0) {
          publish(new Object[] { new String("Row " + row), row,
            col });
        } else {
          // Simulate a slow source
          Thread
            .sleep(new Random().nextInt((250 - 50) + 1) + 50);

          Boolean isSuccessful = false;

          // Simulate a return value
          if (new Random().nextBoolean()) {
            isSuccessful = true;
          }

          publish(new Object[] {
            new String((isSuccessful == true ? "x" : "o")), row,
            col });

          if (isSuccessful == true) {
            break;
          }
        }
      }
    }

    return model;
  }

  @Override
  protected void process(List<Object[]> chunks) {
    for (Object[] chunk : chunks) {
      // chunk[0]: cell value
      // chunk[1]: number
      // chunk[2]: column
      if ((int) chunk[2] == 0) {
        Object[] row = new Object[numCols];
        row[0] = (Object) chunk[0];
        model.addRow(row);
      } else {
        model.setValueAt((Object) chunk[0], (int) chunk[1],
          (int) chunk[2]);
      }
    }
  }
}

这篇关于动态地向JTable添加行 - 为什么它们一次出现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆