2009-11-03 10 views
5

JList 행을 동적으로 변경하려고합니다. 내가 n 번째 행의 색상을 변경해야합니다 (n은 컴파일하는 동안 알 수 없음). 커스텀 ListCellRenderer를 사용한 예제를 많이 보았지만 모두 정적이었습니다.런타임시 JList 행 색상 변경

다른 말로하면 x 행이있는 JList가 있습니다. 런타임 동안 내 "비즈니스 로직"이 n 번째 행을 감지하는 것이 중요합니다. 그래서 나는 그 배경을 초록색으로 만들고 1 초를 기다렸다가 다시 흰 색으로 만들길 원합니다. 한 가지 더, 행 선택을 변경하지 마십시오.

이렇게하는 가장 좋은 방법은 무엇입니까?

+0

msawicki 노트를 사용하는 것이 좋습니다. 즉, 행이 강조 표시되는 동안 GUI에서 다른 작업을 수행 할 수 없습니다. 그리고 내가 다시 말하면 그냥 더러운 샘플입니다 – jitter

+0

좋아, 고마워. 내 버전을 업데이트했습니다. –

답변

5

SUN의 ListDemo 샘플을 기반으로합니다.

목록에없는 텍스트 필드에 텍스트를 입력하고 강조 표시되면 추가됩니다.

텍스트가 목록에 있고 강조 표시를 누르면 목록의 항목이 일시적으로 파란색으로 강조 표시됩니다.

여기 일치 필드가있는 솔루션은 데모 용입니다. 더 정확한 구현을 위해 다른 아이디어를 제안 고려하고 내 대답은 이전 버전의 전체 이벤트 파견 스레드를 차단하는 것이 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

EDT를 잠시 멈추지 않을까요? – akf

+0

감사합니다. 그것은 완벽하게 작동합니다. –

+0

당신은 물론 맞습니다. 스윙 워커 구현으로 대체 됨 – jitter

2

getListCellRendererComponent 메서드를 구현하는 사용자 정의 ListCellRenderer는 JList과 redering되는 값 모두에 액세스 할 수 있습니다.

  1. 당신은 JList를 서브 클래스와 렌더러가되는 색입니다 BG를 위해 사용하도록 요청할 수 : 이렇게하면 녹색 N 번째 행을 그릴 때 확인하는 방법에 대한 몇 가지 옵션을 제공합니다. JList 서브 클래스가 정상
  2. 로 다시 BG를 돌려 다시 그리기를 트리거 할 비즈니스 로직이 N 번째 행은 녹색으로하는 것이 시간을 판단 할 때 다시 그리기를 실행 한 다음 스윙을 Timer를 시작할 수 때 비즈니스 로직 행을 초록색으로 표시해야하는 시점을 결정하면 행의 받침 객체에 상태를 설정하고 getListCellRendererComponent 범위 내에서 해당 상태를 테스트하고 상태가 올바른 경우 bg 녹색을 설정하는 옵션이 있습니다. 다시 말하지만 스윙 Timer을 설정하여 받침 객체의 상태를 되돌릴 수 있습니다.

    list.setCellRenderer(myListCellrenderer); 
    

    지금 오버라이드 (override) 된 메소드의 getListCellRendererComponent 내부() 같은 것을 할 :

6

간단하고 사용하여 JList의에 대한 정의의 ListCellRenderer을 설정

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

위의 예는 가정을 당신의 커스텀 렌더러 오버라이드 DefaultListCellRenderer