1

マルチスレッド プログラムがあり、JTable を使用して各スレッドの進行状況を表示しようとしています。各スレッドは JTable の行です。私が今持っているものの単純化された関連コードを投稿しました。開始を押すたびに、新しいスレッドが開始され、行が JTable に追加されます。しかし、実行中のスレッドからそのスレッドに属する行の「列2」を更新するにはどうすればよいですか?

主にこれは私が持っているものです

JTable table = new JTable(new DefaultTableModel(new Object[]{"Thread Name", "Progress"}, 0));

btnBegin.addActionListener(new ActionListener()
{
  public void actionPerformed(ActionEvent arg0)
  {
    Thread newThread = new Thread(new MyThreadClass(country, category));
    newThread.start();
    DefaultTableModel model = (DefaultTableModel) table.getModel();
    model.addRow(new Object[]{"Thread " + threadNumber, "Column 2"});
  }
});
4

4 に答える 4

3

フィールド tableModel を (フィールド + コンストラクター引数) に追加できる場合MyThreadClass、このクラスから、@sedran が言及したコードを呼び出すことができます。

例:

public class T {

static int threadNumber = 0;

public static void main(String[] args) throws Exception {

    final JTable table = new JTable(new DefaultTableModel(new Object[] { "Thread Name", "Progress" }, 0));

    JButton btnBegin = new JButton("Begin");
    btnBegin.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            DefaultTableModel model = (DefaultTableModel) table.getModel();
            MyThreadClass newThread = new MyThreadClass(model, threadNumber++);
            newThread.start();

            model.addRow(new Object[] { "Thread " + threadNumber, "Column 2" });
        }
    });

    JFrame frame = new JFrame();
    frame.add(btnBegin, BorderLayout.NORTH);
    frame.add(table);
    frame.setSize(400, 400);
    frame.setVisible(true);
}

static class MyThreadClass extends Thread {
    private final DefaultTableModel model;
    private final int threadNumber;

    public MyThreadClass(DefaultTableModel model, int threadNumber) {
        super();
        this.model = model;
        this.threadNumber = threadNumber;
    }

    @Override
    public void run() {
        for (int i = 0; i <= 5; i++) {
            final int index = i;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    model.setValueAt(index * 20, threadNumber, 1);
                }
            });
        }
    }
}

}

SwingUtilities.invokeLaterEDT でビューを更新する必要があるため、 の使用が重要であることに注意してください。

于 2012-08-09T21:22:27.510 に答える
3

実行時に列を更新する場合、および更新する行がわかっている場合は、次のように使用できます。

int row; // row number you want to update.
int column = 1; // You want to update the first row.
DefaultTableModel model = (DefaultTableModel)table.getModel();
Object value = "New Value Of This Cell";
model.setValueAt(value, row, column);

テーブルと、スレッドが表示されている行を MyThreadClass に渡すか設定して、その行を単独で更新できます。

次のように MyThreadClass 内にメソッドを記述できます。

public void setTableAndRow(int row, JTable table) {
    this.table = table;
    this.row = row;
}

スレッドの作成中にこれらの引数を渡すことができます。

btnBegin.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        DefaultTableModel model = (DefaultTableModel) table.getModel();
        MyThreadClass myThread = new MyThreadClass(country, category);
        Thread newThread = new Thread(myThread);
        /**
         * We know, if there is n rows starting from 0,
         * index of the row that we're adding is n.
         */
        int row = model.getRowCount();
        myThread.setTableAndRow(row, table);
        // Now we add the row before starting the thread, because it
        // will try to reach that row, we don't want any exceptions.
        model.addRow(new Object[]{"Thread " + threadNumber, "Column 2"});
        newThread.start();
    }
});
于 2012-08-09T20:57:36.503 に答える
3

提案:

  • SwingWorker オブジェクトを使用して、バックグラウンド スレッドを作成します。
  • SwingWorker から更新を取得する 1 つの方法は、publish/process メソッドのペアを使用することです。これにより、バックグラウンド スレッドは Swing イベント スレッドで Swing アプリケーションにデータを渡すことができます。これにより、バックグラウンド プロセスがデータを GUI に「プッシュ」できるようになります。
  • 更新を取得するもう 1 つの方法は、PropertyChangeListener を SwingWorker に追加し、SwingWorker にバインドされたプロパティを更新させることです。どちらでもうまくいきます。これにより、データをバックグラウンド プロセスから GUI に「プル」することができます。
  • 特定のデータ行のデータを更新するには、モデルの行をフォローしているスレッドに接続する必要があります。getValueAt(...)テーブルモデルの特定の列のセルを、スレッドのデータと一致するデータ、おそらく監視されているクラスのフィールドを含むセルが見つかるまで、いつでも反復できます。次に、JTable のsetValueAt(...)
于 2012-08-09T22:00:14.600 に答える
1

SwingUtilies.invokeLater() が探しているものだと思うので、イベントディスパッチスレッドにアクセスできます。

于 2012-08-09T21:06:05.007 に答える