представьте, что у нас многопользовательская архитектура клиент / сервер. В любое время пользователь может добавить новый TableRow в свой JTable. Сервер получает информацию и отправляет сообщение всем клиентам, поэтому их данные (то есть их табличные представления) также обновляются. Это прекрасно работает, если только пользователь не редактирует строку в этой таблице, в то время как становится updateEvent.
Когда новый tableRow находится выше текущей отредактированной строки от пользователя, соответствующая ячейка также изменяется, но tableEditor не замечает этого, и поэтому неправильная строка редактируется и изменяется сейчас.
Я создал небольшой пример, чтобы разбить эту проблему на несколько строк кода, чтобы мне было легче следовать:
public class TableEventHandlingExample extends JPanel
{
static JFrame frame;
JTable table;
public TableEventHandlingExample()
{
table = new JTable( new StandardTableModel( createTestData() ) );
final Thread thread = new Thread( new Runnable()
{
@Override
public void run()
{
try
{
while ( true )
{
Thread.sleep( 5000 );
((StandardTableModel) table.getModel()).addRow( new Data( 4, "Vier" ), 0 );
}
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
} );
thread.start();
add( new JScrollPane( table ) );
}
private List<Data> createTestData()
{
Data data1 = new Data( 1, "Eins" );
Data data2 = new Data( 2, "Zwei" );
Data data3 = new Data( 3, "Drei" );
List<Data> dataList = new ArrayList<Data>();
dataList.add( data1 );
dataList.add( data2 );
dataList.add( data3 );
return dataList;
}
public static void main( String[] args )
{
frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setLayout( new BorderLayout() );
frame.setBounds( 400, 400, 500, 500 );
frame.add( new TableEventHandlingExample() );
frame.setVisible( true );
}
}
class StandardTableModel extends AbstractTableModel
{
List<Data> dataList;
public StandardTableModel( List<Data> dataList )
{
this.dataList = dataList;
}
@Override
public int getColumnCount()
{
return 2;
}
@Override
public int getRowCount()
{
return dataList.size();
}
@Override
public boolean isCellEditable( int rowIndex, int columnIndex )
{
return true;
}
@Override
public Class<?> getColumnClass( int columnIndex )
{
if ( columnIndex == 0 )
return Integer.class;
return String.class;
}
@Override
public Object getValueAt( int rowIndex, int columnIndex )
{
if ( columnIndex == 0 )
return dataList.get( rowIndex ).getId();
return dataList.get( rowIndex ).getName();
}
@Override
public void setValueAt( Object aValue, int rowIndex, int columnIndex )
{
Data data = dataList.get( rowIndex );
if ( columnIndex == 0 )
data.setId( (Integer) aValue );
else
data.setName( (String) aValue );
}
public void addRow( Data data, int index )
{
if ( index > dataList.size() )
{
return;
}
dataList.add( index, data );
fireTableRowsInserted( index, index );
}
}
class Data
{
private int id;
private String name;
public Data( int id, String name )
{
this.id = id;
this.name = name;
}
public int getId()
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
@Override
public String toString()
{
return getName();
}
}
Для подделки входящих Data-Events я использовал поток, который добавляет новую строку в позицию 1 каждые 5 секунд. Достаточно хорош, чтобы показать, в чем проблема.
У вас есть предложения, как с этим справиться? Должен ли я запретить updateEvents до тех пор, пока таблица редактируется, а потом выполнять updateEvents? Но что я буду делать, когда пользователь будет находиться в режиме редактирования около 5 минут? Извлечение всех обновлений, которые он пропустил, может быть довольно болезненным. Может быть, у вас есть другие идеи?
Заранее спасибо!
ymene