Hans
Hans

Reputation: 1

How does JList repaint?

Please try to run the following example and explain to me why repaint fails to work from time to time especially if you click on a row. It looks like JList forgets about the rows preferred size. I mean that when running this code at fixed intevals, some random interval the JList goes blank.

 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();

 }
}

Upvotes: 0

Views: 2771

Answers (2)

Uhlen
Uhlen

Reputation: 1778

Instead of using java.util.Timer you should use javax.swing.Timer which is designed to work with Swing components, that is most probably your problem.

Swing components may only be modified on the Event Dispatch Thread and the symptoms you describe ("from time to time") is typical when another thread than EDT updates the GUI, it may seem to work fine but then suddenly something "strange" happens.

Upvotes: 2

camickr
camickr

Reputation: 324118

Not sure exactly what the repaint problem is that you are trying to describe.

However, taking a quick look at the code the obvious problem is that you should be using a Swing Timer to do the updates. All changes to Swing components should be done on the Event Dispatch Thread. Since changes to the model will notify the Swing component to update itself the model updateds should be done on the EDT.

Read the section from the Swing tutorial on Concurrency for more information.

Upvotes: 4

Related Questions