스윙 JTable
에는 많은 양의 데이터가 동적으로 업데이트됩니다. 새 행이 지속적으로 추가되고 몇 분 안에 1000-2000 행을 추가 할 수 있습니다. 일부 직원을 수행하기 위해 사용의 단일 행 선택 이벤트에 응답하기 위해 리스너를 등록했습니다. Swing 데이터 바인딩에 Observer 패턴을 사용했으며 테이블의 모델은 WritableList 구현에 의해 뒷받침됩니다. 따라서 새 항목이 자체 영역에서 테이블에 추가됩니다. 그리고 Listener가 SWT UI 스레드에서 추가되었습니다. 문제는 새로운 행이 테이블에 추가되면 사용자 행 선택 이벤트에서 한 번에 응답하지 않는다는 것입니다. 테이블 모델 업데이트를 중지 할 때만 테이블이 사용자 선택에 응답합니다 .- 몇 번 더 지연되고 30-60 초가 걸립니다. 집중적으로 업데이트 할 때 내 테이블 모델이 사용자 선택에 한 번에 응답하지 않는 이유와이 제한을 극복하는 방법을 알려주세요. 제안 사항을 보내 주시면 감사하겠습니다.거대한 데이터로드에서 JTable 행 선택 이벤트에 대한 지연된 응답
5
A
답변
11
SwingWorker
~ publish()
행을 백그라운드로 사용하고 process()
구현에서 TableModel
을 업데이트하십시오. SwingWorker
은 지속 가능한 속도로 업데이트됩니다. limitProfile을 사용하여 event dispatch thread을 차단하지 않도록하십시오.
부록 : GUI는이 1,000,000 행의 variation을 테스트 한대로 반응합니다. 프로파일 링 할 때 "이동"버튼을 클릭 할 때마다 새 작업자가 시작됩니다.
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
/** @see https://stackoverflow.com/a/17415635/230513 */
public class TestTableLoad01 {
public static void main(String[] args) {
new TestTableLoad01();
}
public TestTableLoad01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
final MyTableModel model = new MyTableModel();
JTable table = new JTable(model);
table.setDefaultRenderer(Date.class, new TimeCellRenderer());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.add(new JButton(new AbstractAction("Go") {
@Override
public void actionPerformed(ActionEvent e) {
TableSwingWorker worker = new TableSwingWorker(model);
worker.execute();
}
}), BorderLayout.SOUTH);
}
});
}
public class TimeCellRenderer extends DefaultTableCellRenderer {
private DateFormat df;
public TimeCellRenderer() {
df = new SimpleDateFormat("HH:mm:ss");
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof Date) {
value = df.format(value);
}
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
return this;
}
}
public class MyTableModel extends AbstractTableModel {
private String[] columnNames = new String[]{"Date", "Row"};
private List<RowData> data;
public MyTableModel() {
data = new ArrayList<RowData>(25);
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return columnIndex == 0 ? Date.class : Integer.class;
}
@Override
public String getColumnName(int col) {
return columnNames[col];
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public Object getValueAt(int row, int col) {
RowData value = data.get(row);
return col == 0 ? value.getDate() : value.getRow();
}
public void addRow(RowData value) {
int rowCount = getRowCount();
data.add(value);
fireTableRowsInserted(rowCount, rowCount);
}
public void addRows(RowData... value) {
addRows(Arrays.asList(value));
}
private void addRows(List<RowData> rows) {
int rowCount = getRowCount();
data.addAll(rows);
fireTableRowsInserted(rowCount, getRowCount() - 1);
}
}
public class RowData {
private Date date;
private int row;
public RowData(int row) {
this.date = new Date();
this.row = row;
}
public Date getDate() {
return date;
}
public int getRow() {
return row;
}
}
public class TableSwingWorker extends SwingWorker<MyTableModel, RowData> {
private final MyTableModel tableModel;
public TableSwingWorker(MyTableModel tableModel) {
this.tableModel = tableModel;
}
@Override
protected MyTableModel doInBackground() throws Exception {
// This is a deliberate pause to allow the UI time to render
Thread.sleep(1000);
System.out.println("Start polulating");
for (int index = 0; index < 1000000; index++) {
RowData data = new RowData(index);
publish(data);
Thread.yield();
}
return tableModel;
}
@Override
protected void process(List<RowData> chunks) {
System.out.println("Adding " + chunks.size() + " rows");
tableModel.addRows(chunks);
}
}
}
관련 문제
- 1. jQuery jTable 행 선택
- 2. JTable 행 선택
- 3. JTable 행 선택 해제
- 4. 인서트 된 행 선택 jTable
- 5. 스케이프의 키 이벤트에 대한 응답
- 6. JTable 행 선택 및 데이터 검색
- 7. 데이터를 변경하지 않고 JTable 행 선택
- 8. JTable 선택 및 TableModel
- 9. JTable createAction 응답
- 10. JTable 행의 동색, 행 이동시 행 선택 문제 표시
- 11. 거대한 HttpPost 응답 : JSON
- 12. 이미 발생할 수있는 이벤트에 대한 응답
- 13. 데이터가 변경 될 때의 이벤트에 대한 응답
- 14. 연결된 델파이 컴포넌트 이벤트에 대한 응답
- 15. UIButton 터치 다운 이벤트에 대한 응답
- 16. Windows의 타블렛/마우스 이벤트에 대한 정확한 응답
- 17. JTable 행 헤더의 구현
- 18. 거대한 JSON 응답 처리
- 19. 자바로 색상 이벤트에 응답
- 20. JTable/JScroll 숨겨진 행 및 JTable
- 21. iPad 제스처 인식기 - 지연된 응답
- 22. 재생으로 지연된 HTTP 응답 시작
- 23. DataList의 버튼 이벤트에 응답
- 24. 이벤트에 동적 응답
- 25. 색조 이벤트에 응답 하시겠습니까?
- 26. 누적보기에서 mouseMove 이벤트에 응답
- 27. iPhone의 캘린더 이벤트에 응답
- 28. JTable 행 머리글 텍스트
- 29. 행 삭제 Jtable Jquery
- 30. JTable 행 삭제 오류
귀하의 회신에 감사드립니다, Trashgod. 나는 VisualVM을 사용하고 있었지만 이벤트 디스패치 스레드가 차단되었는지 여부에 대한 많은 정보를 얻지 못했습니다. 이 프로파일 러에서 활성 스레드 목록 만 볼 수 있습니다. 일부 스레드가 다른 스레드에 의해 차단되었는지 여부를 확인하는 방법? 미리 감사드립니다. – kioria
'jvisualvm'에서 정확한 색 구성표가 기억 나지 않습니다. NetBeans에서는 빨간색입니다. [스레드 덤프] (http://javatechniques.com/blog/jdb-example-generating-a-thread-dump/)와 비교하십시오. [example] (http://stackoverflow.com/q/12728589/230513)). – trashgod
새로운 행을 많이 게시하기 위해 생성하고 실행해야하는 스레드의 양에 대해 궁금합니다 ... 스레드 생성과 해체는 칩 작업이 아닙니다. 그리고 SwingWorker 프레임 워크를 사용하면 메소드 doInBackground()를 호출하기 위해 매번 새로운 인스턴스를 생성해야 할 필요가있는 것으로 보입니다. 그것은 효율적입니까? – kioria