2010-02-23 62 views
2

我正在摸索着這個問題。下面是一個運行示例。我在流佈局中有兩個Swing列表,每個列表都有一個簡單的數據模型。根據我如何實例化FlowLayout,第二列表不顯示其元素。奇怪的。這個Swing List爲什麼不顯示它的元素?

import javax.swing.*; 
import java.awt.*; 

public class ListboxTest2 { 

    public static void main(String[] args) { 

     JFrame f = new JFrame(); 
     f.setSize(500, 500); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel panel = new JPanel(); 
     // this works 
     // panel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); 

     // this doesn't 
     panel.setLayout(new FlowLayout()); 

     final JList list1 = new JList(); 
     list1.setPreferredSize(new Dimension(120, 60)); 
     final JList list2 = new JList(); 
     list2.setPreferredSize(new Dimension(120, 60)); 

     final String[] strings1 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"}; 
     final String[] strings2 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"}; 

     list1.setModel(new AbstractListModel() { 

      public int getSize() { 
       return strings1.length; 
      } 

      public Object getElementAt(int index) { 
       return strings1[index]; 
      } 
     }); 
     panel.add(list1); 

     list2.setModel(new AbstractListModel() { 

      public int getSize() { 
       return strings2.length; 
      } 

      public Object getElementAt(int index) { 
       return strings2[index]; 
      } 
     }); 
     panel.add(list2); 

     f.add(panel); 

     f.setVisible(true); 
     list1.grabFocus(); 
     list1.setSelectedIndex(0); 
    } 

} 
+0

您應該使用SwingUtilities.invokeLater在Event Dispatch Thread上啓動GUI。可能解決你的問題。它雖然適用於我。 – willcodejavaforfood 2010-02-23 10:36:17

+0

什麼操作系統和Java?我有Java 6的Windows。 – sproketboy 2010-02-23 10:46:43

+0

pack和使用invokeLater的組合似乎解決了它。但我不明白爲什麼。 (我使用invokeLater做選擇索引和焦點) – sproketboy 2010-02-23 10:52:49

回答

2

這與佈局管理器無關。您需要在JFrame之前致電pack(),否則該行爲有點隨意,因爲您的主線程和EDT之間存在競爭狀態。

從理論上講,UI的所有操作都必須在EDT中進行,包括原始設置。在實踐中,您可以通過在EDT啓動之前完全完成設置來避免這種情況(我相信這通常發生在第一個組件可見時)。我懷疑在你的代碼中,grabFocus()會導致在主線程上計算UI的佈局,然後導致與setVisible()開始的EDT競爭狀態。

+0

這個工程!除了行: list1.grabFocus(); list1.setSelectedIndex(0); 然後list2仍然搞砸了。 – sproketboy 2010-02-23 10:43:09

+0

@Dan:您可能必須使用SwingUtilities.invokeLater()才能在EDT上運行它。 – 2010-02-23 10:51:03

2

在第一次嘗試中,第二個列表中只顯示了一個元素。 在所有後續嘗試中,它顯示正確。 很奇怪。

我會嘗試在初始化的其餘部分之後移動setVisible(true)。

+0

好。我不瘋了。很高興知道。 – sproketboy 2010-02-23 10:33:50

+0

看來: list1.grabFocus(); 有時是罪魁禍首。但我知道爲什麼。 其實,嘗試運行一次或兩次而不改變任何東西。 – sproketboy 2010-02-23 10:38:27

2

將列表框放在JScrollPane中總是一個很好的做法,因爲它允許您在項目超出可見區域時進行滾動。像這樣將列表框添加到面板。

panel.add(new JScrollPane(list1)); 
panel.add(new JScrollPane(list2)); 
+0

是的,我可能會那樣做。在我的情況下,這是一個我有固定空間的遊戲。 – sproketboy 2010-02-23 10:36:48

相關問題