好在SWT中可以嵌入AWT。
反正本人以前沒有過多Swing的經驗,但是在試玩了JTable之后發現確實很強大。
對于有興趣的讀者可以試一下,本文將分享如何使得JTable與JFace Data Binding Framework(下文中簡稱JDBF)一起協同工作。
通常像Table和List這種UI組件,展現的都是一個對象集合。JDBF 則為我們處理對象集合和UI界面的同步的問題。以List為例子,在Java中有java.util.List,而JFDB則提供了相應的
ObservableList類,這個類Wrap一個java.util.List,當你對其進行增刪改時,與其綁定的UI組件會自動得到同步。但是ObservableList 的實現有個很大的問題就是對其的訪問只限于其所屬的Realm,這個Realm說白了就是SWT的UI線程,而當我們在SWT中嵌入AWT時,其中的AWT界面是跑在其自身的線程里面的。所以想要讓JTable與JFace Data Binding Framework(下文中簡稱JDBF)一起協同工作還要解決多線程的問題。廢話不多說了,直接上菜:
public class DOTableModel extends AbstractTableModel {
public class DOTableModel extends AbstractTableModel {
/**
* the ObservableList instance to be shared with
*/
private ObservableList list;
private volatile Integer rowCount = null;
private volatile DOModel object;;
private final Object lock = new Object();
private static final long serialVersionUID = -8377145381412656796L;
public DOTableModel(ObservableList list){
this.list = list;
this.list.addListChangeListener(new IListChangeListener(){
@Override
public void handleListChange(ListChangeEvent event) {
for(ListDiffEntry de : event.diff.getDifferences()){
if(de.isAddition()){
DOTableModel.this.fireTableRowsInserted(de.getPosition(), de.getPosition());
}else{
DOTableModel.this.fireTableRowsDeleted(de.getPosition(), de.getPosition());
}
}
}
});
}
@Override
public int getRowCount() {
list.getRealm().exec(new Runnable(){
@Override
public void run() {
rowCount = list.size();
synchronized (lock) {
lock.notify();
}
}
});
synchronized (lock) {
while(rowCount == null){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return rowCount;
}
@Override
public int getColumnCount() {
return 11;
}
private void getObjectFromSWTRealm(final int rowIndex){
object = null;
list.getRealm().exec(new Runnable(){
@Override
public synchronized void run() {
object = (DOModel) list.get(rowIndex);
synchronized (lock) {
lock.notify();
}
}
});
synchronized (lock) {
while(object == null){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public Object getValueAt(final int rowIndex, int columnIndex) {
getObjectFromSWTRealm(rowIndex);
...
}
@Override
public void setValueAt(Object oValue, final int rowIndex, int columnIndex) {
getObjectFromSWTRealm(rowIndex);
...
}
@Override
public String getColumnName(int column) {
...
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
}
* the ObservableList instance to be shared with
*/
private ObservableList list;
private volatile Integer rowCount = null;
private volatile DOModel object;;
private final Object lock = new Object();
private static final long serialVersionUID = -8377145381412656796L;
public DOTableModel(ObservableList list){
this.list = list;
this.list.addListChangeListener(new IListChangeListener(){
@Override
public void handleListChange(ListChangeEvent event) {
for(ListDiffEntry de : event.diff.getDifferences()){
if(de.isAddition()){
DOTableModel.this.fireTableRowsInserted(de.getPosition(), de.getPosition());
}else{
DOTableModel.this.fireTableRowsDeleted(de.getPosition(), de.getPosition());
}
}
}
});
}
@Override
public int getRowCount() {
list.getRealm().exec(new Runnable(){
@Override
public void run() {
rowCount = list.size();
synchronized (lock) {
lock.notify();
}
}
});
synchronized (lock) {
while(rowCount == null){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return rowCount;
}
@Override
public int getColumnCount() {
return 11;
}
private void getObjectFromSWTRealm(final int rowIndex){
object = null;
list.getRealm().exec(new Runnable(){
@Override
public synchronized void run() {
object = (DOModel) list.get(rowIndex);
synchronized (lock) {
lock.notify();
}
}
});
synchronized (lock) {
while(object == null){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public Object getValueAt(final int rowIndex, int columnIndex) {
getObjectFromSWTRealm(rowIndex);
...
}
@Override
public void setValueAt(Object oValue, final int rowIndex, int columnIndex) {
getObjectFromSWTRealm(rowIndex);
...
}
@Override
public String getColumnName(int column) {
...
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
}