2009-11-03 6 views
5

Próbuję dynamicznie zmieniać wiersze JList. Potrzebuję zmienić kolor n-tego wiersza, podświetlić go (n jest nieznany podczas kompilacji). Widziałem wiele przykładów z niestandardowym narzędziem ListCellRenderer, ale wszystkie były "statyczne".Zmiana koloru wiersza JList w czasie wykonywania

Innymi słowy Mam JList z x rzędami. W czasie działania moja "logika biznesowa" wykrywa n-ty wiersz jest ważny. Więc chcę, aby jego tło było zielone, poczekaj sekundę, a potem znowu biel. Jeszcze jedno, nie zmieniaj wyboru wiersza.

Jaki jest najlepszy sposób na zrobienie tego?

+0

msawicki uwagę, że poprzednia wersja moją odpowiedź będzie blokować cały wątek wysyłki wydarzenie. co oznacza, że ​​gdy wiersz jest podświetlony, nie możesz zrobić nic więcej w gui. i powtarzam, że to jest po prostu szybka, brudna próbka. – jitter

+0

OK, dziękuję. Zaktualizowałem swoją wersję. –

Odpowiedz

5

Na podstawie próbki ListDemo z SUN.

Jeśli wprowadzisz jakiś tekst w polu tekstowym, którego nie ma na liście, a naciśniesz zaznaczenie, zostanie ono dodane.

Jeśli tekst znajduje się na liście i zaznaczysz, pozycja na liście zostanie tymczasowo podświetlona na niebiesko.

Pamiętaj, że rozwiązanie tutaj z polem dopasowania jest tylko dla wersji demonstracyjnej. Aby uzyskać więcej prawidłowej realizacji rozważyć proponowane inne pomysły i rozważyć użycie javax.swing.Timer

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

public class ListDemo extends JPanel { 
    private JList list; 
    private DefaultListModel listModel; 
    public String match = null; 

    private static final String hireString = "Highlight"; 
    private JTextField employeeName; 

    public ListDemo() { 
     super(new BorderLayout()); 

     listModel = new DefaultListModel(); 
     listModel.addElement("Test1"); 
     listModel.addElement("Test2"); 
     listModel.addElement("Test3"); 

     list = new JList(listModel); 
     list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     list.setSelectedIndex(0); 
     list.setVisibleRowCount(5); 
     list.setCellRenderer(new MyListCellRenderer()); 
     JScrollPane listScrollPane = new JScrollPane(list); 

     JButton hireButton = new JButton(hireString); 
     HireListener hireListener = new HireListener(hireButton); 
     hireButton.setActionCommand(hireString); 
     hireButton.addActionListener(hireListener); 
     hireButton.setEnabled(false); 

     employeeName = new JTextField(10); 
     employeeName.addActionListener(hireListener); 
     employeeName.getDocument().addDocumentListener(hireListener); 
     listModel.getElementAt(list.getSelectedIndex()).toString(); 

     JPanel buttonPane = new JPanel(); 
     buttonPane.setLayout(new BoxLayout(buttonPane, 
              BoxLayout.LINE_AXIS)); 
     buttonPane.add(Box.createHorizontalStrut(5)); 
     buttonPane.add(employeeName); 
     buttonPane.add(hireButton); 
     buttonPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 

     add(listScrollPane, BorderLayout.CENTER); 
     add(buttonPane, BorderLayout.PAGE_END); 
    } 
    class MyListCellRenderer extends JLabel implements ListCellRenderer { 
     public MyListCellRenderer() { 
      setOpaque(true); 
     } 
     public Component getListCellRendererComponent(JList paramlist, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
      setText(value.toString()); 
      if (value.toString().equals(match)) { 
       setBackground(Color.BLUE); 
       SwingWorker worker = new SwingWorker() { 
        @Override 
        public Object doInBackground() { 
         try { 
          Thread.sleep(5000); 
         } catch (InterruptedException e) { /*Who cares*/ } 
         return null; 
        } 
        @Override 
        public void done() { 
         match = null; 
         list.repaint(); 
        } 
       }; 
       worker.execute(); 
      } else 
       setBackground(Color.RED); 
      return this; 
     } 
    } 
    class HireListener implements ActionListener, DocumentListener { 
     private boolean alreadyEnabled = false; 
     private JButton button; 
     public HireListener(JButton button) { 
      this.button = button; 
     } 
     public void actionPerformed(ActionEvent e) { 
      String name = employeeName.getText(); 
      if (listModel.contains(name)) { 
       match = name; 
       list.repaint(); 
       employeeName.requestFocusInWindow(); 
       employeeName.selectAll(); 
       return; 
      } 
      if (name.equals("")) { 
       Toolkit.getDefaultToolkit().beep(); 
       employeeName.requestFocusInWindow(); 
       employeeName.selectAll(); 
       return; 
      } 
      int index = list.getSelectedIndex(); 
      if (index == -1) 
       index = 0; 
      else 
       index++; 
      listModel.insertElementAt(employeeName.getText(), index); 
      employeeName.requestFocusInWindow(); 
      employeeName.setText(""); 
      list.setSelectedIndex(index); 
      list.ensureIndexIsVisible(index); 
     } 
     public void insertUpdate(DocumentEvent e) { 
      enableButton(); 
     } 
     public void removeUpdate(DocumentEvent e) { 
      handleEmptyTextField(e); 
     } 
     public void changedUpdate(DocumentEvent e) { 
      if (!handleEmptyTextField(e)) 
       enableButton(); 
     } 
     private void enableButton() { 
      if (!alreadyEnabled) 
       button.setEnabled(true); 
     } 
     private boolean handleEmptyTextField(DocumentEvent e) { 
      if (e.getDocument().getLength() <= 0) { 
       button.setEnabled(false); 
       alreadyEnabled = false; 
       return true; 
      } 
      return false; 
     } 
    } 
    private static void createAndShowGUI() { 
     JFrame frame = new JFrame("ListDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JComponent newContentPane = new ListDemo(); 
     newContentPane.setOpaque(true); 
     frame.setContentPane(newContentPane); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { createAndShowGUI(); } 
     }); 
    } 
} 
+0

czy to nie przerwałoby EDT na sekundę? – akf

+0

Dziękuję. Działa idealnie. –

+0

masz rację oczywiście. zastąpiony przez implementację swingworkera – jitter

2

Twój niestandardowy narzędzie ListCellRenderer, które implementuje metodę getListCellRendererComponent, będzie mieć dostęp do wartości JList i wartości, którą ponownie zmienia. To daje kilka opcji do sposobu ustalania, kiedy pomalować n th wiersz green:

  1. Można podklasa JList i mają renderujący poprosić go jakiego koloru użyć do BG. JList podklasa może wywołać repaint kiedy logika biznesowa określa, że ​​jest to czas dla n th rząd będzie zielony, a następnie uruchom an swing Timer aby wywołać repaint zwrotu bg powrót do normalnego
  2. Kiedy logika biznesowa określa, kiedy powinieneś pokazać wiersz jako zielony, możesz także ustawić stan na obiekcie podkładu wiersza i przetestować go dla tego stanu w zakresie getListCellRendererComponent, ustawiając wartość bg na zielono, jeśli stan jest poprawny. Ponownie, masz możliwość ustawienia Swing Timer, aby przywrócić stan w obiekcie podkładu.
6

Prosty, ustawić niestandardowy ListCellRenderer do swojego JList przy użyciu:

list.setCellRenderer(myListCellrenderer); 

Teraz wewnątrz zastąpionej metodzie getListCellRendererComponent() zrobić coś takiego:

public Component getListCellRendererComponent(.....) { 
    Component c = super.getListCellRendererComponent(); 
    c.setBackGround(Color.blue) 
    return c; 
} 

Powyższy przykład zakłada, że ​​Twój niestandardowy renderer renderujący DefaultListCellRenderer