İçindekilerGirişİndex
YukarıİlkÖncekiSonrakiSon
Geriİleri
Yazdır
Zafer Teker
tekzaf@yahoo.com

Bir Liste Component'i Örneği

Note Defteri/Word Wrap programlarında Font ayarlarının yapıldığı dilaog penceresinde listeler bulunmaktadır. Örneğin font isimlerinin bulunduğu bir liste bulunmaktadır. Bu listenin üstünde bir text alanı vardır. Listeden herhangi bir madde seçilince o text alanınada bu madde görüntülenir. Text alanınada yazı yazılınca yazılan yazıya yakın maddeler görüntülenir. Örneğin T harfi yazılır yazılmaz Tahoma font'u gözükür hale gelir. İşte bizim yaptığımız komponent bu işlemleri yapmak içindir.

Bu component''te bir label,bir text field ve bir liste kullanılmaktadır. Listeden herhangi madde seçildiğinde text alanında o madde gözükür. Text alanınada yazı girildiğinde girilen yazıya yakın element'ler listede görünür hale gelir.

Göster Gizle Kopar Satır Gizle Satır Göster
  1 package com.godoro.swing;
  2 import javax.swing.*;
  3 import javax.swing.event.*;
  4 import java.awt.*;
  5 import java.util.*;
  6 public class TextList extends JPanel
  7     implements ListSelectionListener,DocumentListener,Runnable
  8 {
  9   private JTextField theField;
 10   private JList theList;
 11   private JLabel theLabel;
 12   public TextList(String label,JList list){
 13     theList=list;
 14     theLabel=new JLabel(label);
 15     theField=new JTextField();
 16     theList.addListSelectionListener(this);
 17     theField.getDocument().addDocumentListener(this);
 18     JPanel upPanel=new JPanel();
 19     upPanel.setLayout(new GridLayout(2,1));
 20     upPanel.add(theLabel);
 21     upPanel.add(theField);
 22     setLayout(new BorderLayout());
 23     add(upPanel,BorderLayout.NORTH);
 24     add(new JScrollPane(theList),BorderLayout.CENTER);
 25   }
 26   public String getSelected(){
 27     return (String)theList.getSelectedValue();
 28   }
 29   public String getText(){
 30     return theField.getText();
 31   }
 32   public void run(){
 33     updateSelect();
 34   }
 35   public void valueChanged(ListSelectionEvent e){
 36     if(theList.getSelectedValue()!=null){
 37       String select=(String)theList.getSelectedValue();
 38       theField.setText(select);
 39     }
 40   }
 41   public void changedUpdate(DocumentEvent e){
 42      SwingUtilities.invokeLater(this);
 43   }
 44   public void insertUpdate(DocumentEvent e){
 45     SwingUtilities.invokeLater(this);
 46   }
 47   public void removeUpdate(DocumentEvent e){
 48     SwingUtilities.invokeLater(this);
 49   }
 50   private void updateSelect(){
 51     if(theField.getText()!=null){
 52       String text=theField.getText();
 53       viewListItem(text);
 54     }
 55   }
 56   private void viewListItem(String text){
 57     if(contains(text)){
 58       theList.setSelectedValue(text,true);
 59     }else{
 60       String item=getNearItem(text);
 61       if(item!=null){
 62         int index=getIndex(item);
 63         if(index!=-1){
 64           theList.clearSelection();
 65           theList.ensureIndexIsVisible(index);
 66         }
 67       }
 68     }
 69   }
 70   private String getNearItem(String text){
 71     ListModel model=theList.getModel();
 72     int size=model.getSize();
 73     for(int i=0;i<size;i++){
 74       String item=(String)model.getElementAt(i);
 75       if(item.compareToIgnoreCase(text)>0){
 76         return item;
 77       }
 78     }
 79     return null;
 80   }
 81   private boolean contains(String text){
 82     ListModel model=theList.getModel();
 83     int size=model.getSize();
 84     for(int i=0;i<size;i++){
 85       String item=(String)model.getElementAt(i);
 86       if(item.equalsIgnoreCase(text)){
 87         return true;
 88       }
 89     }
 90     return false;
 91   }
 92   private int getIndex(String text){
 93     ListModel model=theList.getModel();
 94     int size=model.getSize();
 95     for(int i=0;i<size;i++){
 96       String item=(String)model.getElementAt(i);
 97       if(item.equalsIgnoreCase(text)){
 98         return i;
 99       }
100     }
101     return -1;
102   }
103   public static void main(String[] args) {
104     JFrame frame=new JFrame();
105     frame.setBounds(0,0,200,300);
106     String[] items=new String[]{"ali","bae","bge","cdd","fsd","fzfg","fzh","hgt","mmn",
107       "mss","nnb","oo","ozz","ttt","uuu","vvv","zsd","zzz"};
108     JList list=new JList(items);
109     TextList textList=new TextList("Test",list);
110     frame.getContentPane().setLayout(new BorderLayout());
111     frame.getContentPane().add(textList,BorderLayout.CENTER);
112     frame.setVisible(true);
113   }
114 }

Bir listeden bir item seçildiğinde anlayabilmemiz için ListSelectionListener interface'ni implements ettik ve

public void valueChanged(ListSelectionEvent e){
	if(theList.getSelectedValue()!=null){
   String select=(String)theList.getSelectedValue();
		theField.setText(select);
	}
}

methodu yazdık. Bu method'da listeden seçilen değeri alıyoruz ve text field'te gösteriyoruz. Text field'de yazı girilmesini takip etmek için DocumentListener interface'ni implements ettik ve

  public void changedUpdate(DocumentEvent e){
     SwingUtilities.invokeLater(this);
  }
  public void insertUpdate(DocumentEvent e){
    SwingUtilities.invokeLater(this);
  }
  public void removeUpdate(DocumentEvent e){
    SwingUtilities.invokeLater(this);
  }

method'larını yazdık. Dinlemek için

theField.getDocument().addDocumentListener(this);

şeklinde TextList class'ı kendisini kaydetti. Dikkat edilirse SwingUtilities.invokeLater methodunu kullanıyoruz. Bunun sebebi şu. Text alanında bir yazı girildiğinde eğer listede girilen yazı varsa yazı seçili hale getiriliyor. Listede seçim yapılınca da text alanına seçilen element yazılıyor. Bu lock sorunu yaratıyor. Çünkü text alanında bir değişiklik yapıldığında changedUpdate,insertUpdate,removeUpdate methodu çağrılıyor. Bu method'lar tamamlanmadan başka hiç bir program text alanını set edemez. SwingUtilities.invokeLater ile text alanına daha sonra set etmek istediğimizi bildiriyoruz. Bylece bu sorun hallediliyor. Bu işlem eğer SwingUtilities.invokeLater ile yapılmassa aşağıdaki Exception oluşmakta.

java.lang.IllegalStateException: Attempt to mutate in notification

Bu exceptionu engellemek için SwingUtilities.invokeLater ile ayrı bir thread yaratıyoruz.

public void run(){
	updateSelect();
}

updateSelect method'u viewListItem method'unu çağırmakta. viewListItem valueChanged method'unun çağrılmasına sebe olabilir. Bu method'da setText'i çağırıyor. İşlem ayrı thread'te yapıldığında setText yukarıdaki exception'u vermiyor.

Text alanınada bir yazı girildiğinde getNearItem mewthod'u ile en yakın madde bulunarak görünmesi sağlanıyor. Bir liste maddesi ensureIndexIsVisible method ile görünmesi sağlanabiliyor.

Sonuç olarak bu component kullanıcıdan bir liste içinden seçim yapmasını sağlamak için kullanılabilir.

Dosya Listesi

İçindekilerGirişİndex
YukarıİlkÖncekiSonrakiSon
Geriİleri
Yazdır