2011-02-01 19 views
2

我有JXTable的錶行選擇問題。JXTable + GlazedLists +在拖動選擇期間更新=問題

如果我運行以下程序,我會看到兩個幀正在查看相同的EventList<Item>。一個有JTable,另一個有JXTable。

每1000毫秒我更新名稱以foo開頭的所有項目(這發生在tweakList())。此更新似乎會干擾JXTable中的鼠標選擇,但不會影響JTable:如果在JXTable中單擊並向下拖動以選擇多行,則選擇定位點會在更新發生時消失。 (點擊並向上拖動工作正常)

它爲什麼這樣做,我該如何解決這個問題?

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.HashSet; 
import java.util.Set; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.Timer; 
import org.jdesktop.swingx.JXTable; 
import ca.odell.glazedlists.BasicEventList; 
import ca.odell.glazedlists.EventList; 
import ca.odell.glazedlists.SortedList; 
import ca.odell.glazedlists.gui.TableFormat; 
import ca.odell.glazedlists.swing.EventTableModel; 

public class TableSelectionExample { 
    static public enum ItemKey { 
     NAME("name") { 
      @Override public String getStringFromItem(Item item) { 
       return item.getName(); 
      } 
     }, 
     NUMBER("#") { 
      @Override public String getStringFromItem(Item item) { 
       return Integer.toString(item.getNumber()); 
      } 
     }, 
     PARENT("parent") { 
      @Override public String getStringFromItem(Item item) { 
       Item p = item.getParent(); 
       return (p == null) ? null : p.getName(); 
      }   
     }; 

     final private String name; 
     ItemKey(String name) { this.name = name; } 
     public String getName() { return this.name; } 
     abstract public String getStringFromItem(Item item); 

     static private ItemKey[] columns = { NAME, NUMBER, PARENT }; 
     static public ItemKey[] getColumns() { return columns; } 
    } 
    static public class ItemTableFormat implements TableFormat<Item> { 
     @Override public int getColumnCount() { 
       return ItemKey.getColumns().length; 
      } 
     @Override public String getColumnName(int col) { 
      return ItemKey.getColumns()[col].getName(); } 
     @Override public Object getColumnValue(Item item, int col) { 
      return ItemKey.getColumns()[col].getStringFromItem(item); 
     }  
    } 

    static class Item { 
     final private String name; 
     private int number; 
     final private Item parent; 

     private Item(String name, int number, Item parent) { 
      this.name=name; this.number=number; this.parent=parent; 
     } 
     static public Item create(String name, int number, Item parent) { 
      return new Item(name, number, parent); 
     } 

     public String getName() { return this.name; } 
     public int getNumber() { return this.number; } 
     public void setNumber(int number) { this.number = number; } 
     public Item getParent() { return this.parent; } 
    } 

    static public void main(String[] args) 
    { 
     final EventList<Item> items = new BasicEventList<Item>(); 
     Item x1,x2,x3; 
     x1 = Item.create("foo", 1, null); 
     x2 = Item.create("bar", 2, x1); 
     x3 = Item.create("baz", 3, x1); 
     items.add(x1); 
     items.add(x2); 
     items.add(x3); 
     for (int i = 0; i < 20; ++i) 
     { 
      items.add(Item.create(String.format("bar%02d",i), 100+i, x2)); 
      items.add(Item.create(String.format("baz%02d",i), 200+i, x3)); 
      if (isprime(i)) 
       items.add(Item.create(
         String.format("foo%02d", i), 300+i, x1)); 
     } 

     EventList<Item> sortedItems = new SortedList<Item>(items, null); 

     doit(sortedItems, new JTable(), "JTable selection example"); 
     doit(sortedItems, new JXTable(), "JXTable selection example"); 

     Timer timer = new Timer(1000, new ActionListener() { 
      @Override public void actionPerformed(ActionEvent e) { 
       tweakList(items);    
      }   
     }); 
     timer.start(); 
    } 

    private static void doit(EventList<Item> displayItems, 
      JTable table, String title) { 
     TableFormat<Item> tf = new ItemTableFormat(); 
     EventTableModel<Item> etm = 
      new EventTableModel<Item>(displayItems, tf); 

     table.setModel(etm);   
     if (table instanceof JXTable) 
     { 
      ((JXTable)table).setColumnControlVisible(true); 
     } 

     JPanel panel = new JPanel(); 
     panel.setLayout(new BorderLayout()); 
     panel.add(new JScrollPane(table), BorderLayout.CENTER); 

     JFrame frame = new JFrame(title); 
     frame.getContentPane().add(panel); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.pack(); 
    } 

    private static boolean isprime(int i) { 
     // works for i < 400 
     if (i < 2) 
      return false; 
     else if (i > 2 && (i % 2) == 0) 
      return false; 
     else if (i > 3 && (i % 3) == 0) 
      return false; 
     else if (i > 5 && (i % 5) == 0) 
      return false; 
     else if (i > 7 && (i % 7) == 0) 
      return false; 
     else if (i > 11 && (i % 11) == 0) 
      return false; 
     else if (i > 13 && (i % 13) == 0) 
      return false; 
     else if (i > 17 && (i % 17) == 0) 
      return false; 
     else if (i > 19 && (i % 19) == 0) 
      return false; 
     else 
      return true; 
    } 

    protected static void tweakList(EventList<Item> items) { 
     int L = items.size(); 
     Set<Integer> modifiedItems = new HashSet<Integer>(); 
     for (int i = 0; i < L; ++i) 
     { 
      Item item = items.get(i); 
      if (item.getName().startsWith("foo")) 
      { 
       item.setNumber(item.getNumber()+1000); 
       modifiedItems.add(i); 
      } 
     } 
     refreshModifiedItems(items, modifiedItems); 
    } 

    private static void refreshModifiedItems(EventList<Item> items, 
      Set<Integer> modifiedItems) { 
     for (int i : modifiedItems) 
     { 
      items.set(i, items.get(i)); 
     } 
    } 
} 

回答

0

沒關係,這是SwingX Issue 370它在SwingX 1.6中得到了修復。

(我正在運行SwingX 1.0;我下載了SwingX 1.6.2並且問題消失了)