如何在线程中启动doLayout()?

时间:2016-01-10 20:31:45

标签: java multithreading swing

您如何看待这样的事情:

public class HeavyJTable extends JTable implements Runnable {
public HeavyJTable (AbstractTableModel m) {
    super(m);
    /* .... */
    this.setAutoResizeMode(AUTO_RESIZE_OFF);
    this.setFillsViewportHeight(false);
}

@Override
public void run() {
    final TableColumnModel columnModel = this.getColumnModel();
    int width = 60;
    for (int column = 0; column < this.getColumnCount(); column++) {
        TableCellRenderer renderer = this.getCellRenderer(0, column);
        Component comp = this.prepareRenderer(renderer, 0, column);
       if(comp == null)
            continue;
        width = Math.max(comp.getPreferredSize().width + 1, width);
        columnModel.getColumn(column).setPreferredWidth(width);
    }
    super.doLayout();
}

@Override
public void doLayout() {
    if (getColumnModel().getTotalColumnWidth() == getWidth()) { 
        return; //filter some useless refreshes
    } else
        new Thread(this).start();
}

}

上下文:我在JTable的不同标签中有几个JTabbedPane,它们监听更新/插入/删除并单独更新自己的数据。所有这些表都可以从微调器中调整大小。所以这是很多数据和很多刷新。

所以我想把所有的绘画过程都放在另一个线程中(每个明智的部分都受到信号量的保护)。

您如何看待这个?还有其他更好的选择吗?我正在考虑SwingWorkers。或者在不同的线程池中运行doLayout()集。

1 个答案:

答案 0 :(得分:2)

Swing不是线程安全的,你不应该做任何事情(直接或间接),它将从事件调度线程的上下文之外更新或更改UI。有关详细信息,请参阅Concurrency in Swing

  

所以我想把所有的绘画过程都放在另一个线程中(每个明智的部分都受到信号量的保护)。

不,这不是绘画的作用。绘画总是在事件调度线程的上下文中完成(绘制事件已插入到EventQueue)。有关详细信息,请参阅Painting in AWT and Swing

  

上下文:我在JTabbedPane的不同选项卡中有几个JTable,它们监听更新/插入/删除并单独更新自己的数据。所有这些表都可以从微调器中调整大小。所以它有很多数据和大量的刷新。

将数据管理与您的视图分开。使用后台线程从EDT加载数据,然后在完成后重新同步结果

  

您如何看待这个?还有其他更好的选择吗?我正在考虑SwingWorkers。或者在不同的线程池中运行doLayout()集。

SwingWorker是一个更好的解决方案,但您可以使用它来加载数据(在doInBackground方法中)并通过process / {{1更新UI功能或publish方法取决于您的需求