2010-11-21 25 views
0

次の例を実行して、特に行をクリックしたときに再描画が失敗する理由を説明してください。 JListは、行の優先サイズを忘れているようです。 固定コードでこのコードを実行すると、JListが空白になるランダムな間隔があることを意味します。JListはどのように再描画されますか?

import javax.swing.JList; 
import javax.swing.ListCellRenderer; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JFrame; 
import javax.swing.BorderFactory; 
import javax.swing.DefaultListModel; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.util.Timer; 
import java.util.TimerTask; 
class ListItem 
{ 
private Color color; 
private String value; 
public ListItem(Color c, String s) 
{ 
    color = c; 
    value = s; 
} 
public Color getColor() 
{ 
    return color; 
} 
public String getValue() 
{ 
    return value; 
} 
} 

class MyCellRenderer extends 
JLabel implements ListCellRenderer 
{ 
public MyCellRenderer() 
{ 
    setOpaque(true); 
} 
public Component getListCellRendererComponent(JList list, 
    Object value, // value to display 
     int index, // cell index 
     boolean iss, // is selected 
     boolean chf) // cell has focus? 
{ 
    System.out.println(" i cell-rendering "+CustomList.tid + " " 
    + CustomList.model.getSize() + " " + index+" "+CustomList.statusList.getValueIsAdjusting() + " "); 
    setText(((ListItem)value).getValue()); 
    setBackground(((ListItem)value).getColor()); 
    if (iss) 
    { 
    setBorder(BorderFactory.createLineBorder(Color.blue, 1)); 
    } 
    else 
    { 
    setBorder(BorderFactory.createLineBorder(list.getBackground(), 1)); 
    } 
    return this; 
} 
} 

public class CustomList 
{ 
public static DefaultListModel model; 
public static JList statusList; 
public static int tid = 0; 

public static void tidUr() 
{ 
    int delay = 1000; 
    int period = 1000; 
    Timer timer = new Timer(); 
    timer.scheduleAtFixedRate(new TimerTask() 
    { 
    public void run() 
    { 
    // model = new DefaultListModel(); 
    // statusList.setModel(model); 
    // statusList.setCellRenderer(new MyCellRenderer()); 
    model.clear(); 
    tid++; 
    ListItem li = new ListItem(Color.cyan, "test line one "+tid); 
    model.addElement(li); 
    li = new ListItem(Color.yellow, "foo foo foo foo foo"); 
    model.addElement(li); 
    li = new ListItem(Color.green, "quick brown fox"); 
    model.addElement(li); 
    } 
    }, delay, period); 
} 

public static void main(String args[]) 
{ 
    JFrame frame = new JFrame("Custom List Demo"); 
    frame.addWindowListener(new WindowAdapter() 
    { 
    public void windowClosing(WindowEvent e) 
    { 
    System.exit(0); 
    } 
    } 
    ); 

    model = new DefaultListModel(); 
    statusList = new JList(model); 
    statusList.setCellRenderer(new MyCellRenderer()); 

    ListItem li = new ListItem(Color.cyan, "test line one"); 
    model.addElement(li); 
    li = new ListItem(Color.yellow, "foo foo foo foo foo"); 
    model.addElement(li); 
    li = new ListItem(Color.green, "quick brown fox"); 
    model.addElement(li); 

    JPanel panel = new JPanel(); 
    panel.add(statusList); 
    frame.getContentPane().add("Center", panel); 
    frame.setLocation(300, 400); 
    frame.setSize(200, 200); 
    //frame.pack(); 
    frame.setVisible(true); 

    // tidUr(); 
    ActionListener actionListener = new ActionListener() { 
     public void actionPerformed(ActionEvent actionEvent) { 
      System.out.println("Hello World Timer"); 
      model.clear(); 
      tid++; 
      ListItem li = new ListItem(Color.cyan, "test line one "+tid); 
      model.addElement(li); 
      li = new ListItem(Color.yellow, "foo foo foo foo foo"); 
      model.addElement(li); 
      li = new ListItem(Color.green, "quick brown fox"); 
      model.addElement(li); 
     } 
     }; 

    javax.swing.Timer t2 = new javax.swing.Timer(1000, actionListener); 
    t2.start(); 

} 
} 

答えて

4

説明しようとしている再ペイントの問題が正確にわからない。

しかし、コードを簡単に見てみると、スウィングタイマーを使用して更新を行うべきであるということが明らかです。 Swingコンポーネントに対するすべての変更は、Event Dispatch Threadで行う必要があります。モデルを変更するとSwingコンポーネントに通知され、モデルを更新する必要があります。モデルの更新はEDTで行う必要があります。

詳細については、ConcurrencyのSwingチュートリアルのセクションをお読みください。

+0

ありがとうございました!これは問題を解決し、java.util.TimerがSwingと結合するのに不適格であることを知りました – Hans

+0

ActionListener actionListener = new ActionListener(){ public void actionPerformed(ActionEvent actionEvent){ System.out.println( "Hello World Timer") ; \t \t \t \t model.clear(); \t \t \t \t tid ++; \t \t \t \t ListItem li =新しいListItem(Color.cyan、 "test line one" + tid); \t \t \t \t model.addElement(li); \t \t \t \t li = new ListItem(Color.yellow、 "foo foo foo foo foo"); \t \t \t \t model.addElement(li); \t \t \t \t li =新しいListItem(Color.green、 "quick brown fox"); \t \t \t \t model.addElement(li); } }; \t \t \t \t javax.swing.Timer t2 = new javax.swing.Timer(1000、actionListener); \t \t t2.start(); – Hans

2

java.util.Timerの代わりにjavax.swing.Timerを使用してください。これは、おそらくあなたの問題であるSwingコンポーネントで動作するように設計されています。 EDTよりも別のスレッドがGUIを更新したときに、それが正常に動作するように見えるかもしれ

Swingコンポーネントのみイベントディスパッチスレッド変更することがも、あなたが(「随時」)を記述症状が典型的ですが、突然、「奇妙な」何かが起こります。

+0

JTableはjava.util.Timerとjavax.swing.Timerの両方で動作します。 JListはjavax.swingでのみ動作します:Timer – Hans

+1

java.util.Timerでうまくいくように見えるかもしれませんが、Swingのシングルスレッドポリシー違反です。 – Uhlen

関連する問題