스윙에서는 외형이 사용자의 맘에 들지 않으면 단순히 변경할 수 있었다. 이번 팁에서는JFileChooser컴포넌트의 외형과 그것의 속성을 사용자 정의하는 방법을 배우게 될 것이다. 먼저JFileChooser의 사용법을 복습해보자. 그리고 컴포넌트를 이용한 단일/다중 선택과 파일/디렉토리의 선택, 파일의 세팅과 현재 선택된 컨텐츠를 미리 보기할 때 필요한 액세서리를 추가하는 과정, 마지막으로 파일 리스트 뷰 영역을 업데이트하는 것을 공부하기로 하겠다.

기본적인 사용법

JFileChooser컴포넌트는 시스템에서 사용하고자 하는 파일과 디렉토리를 선택할 수 있는 방법을 제공한다. 이 컴포넌트는 하나 이상의 파일이나 디렉토리를 선택할 수 있는 다이알로그를 제공한다.JFileChooser컴포넌트에 포함된 것들은 다이알로그의 모달 버전을 보여주기 위한 메소드들의 집합이다. 모달이란, 사용자가 어떤 항목을 선택하지 않는 한 메소드가 값을 리턴하지 않는 것을 말한다. 이러한 메소드로는showOpenDialog,showSaveDialog,showDialog가 있다. 이 3개의 메소드는 승인 버튼에 어떤 텍스트가 나타날 것인지를 조절한다. (즉, 이 텍스트는 다이얼로그를 이용한 작업이 끝났을 때 사용자가 선택한 사항이다.) Open 과 Save 와 같은 일반적인 옵션에 관해서는 물론 빌트인(built-in) 메소드가 존재한다. 디스플레이되는 파일 선택창 다이알로그는 현재의 룩앤필 세팅에 적절하게 맞춰져 있다. 일반적으로 다이알로그는 사용자의 플랫폼에 적합한 파일 다이알로그로 보이고, 특별히 설정된 사항이 없다면 크로스 플랫폼의 Metal 룩앤필로 설정된다.

사용자는 다이알로그에서 항목을 선택하고 Open 이나 Save 버튼을 클릭하거나 선택된 항목을 더블 클릭한다. 그러면 Show 메소드는 승인 버튼이 선택된 것인지, 아니면 사용자가 항목을 선택하지 않고 다이알로그를 닫아버렸는지(사용자가 Cancel 버튼이나 윈도우 상위 코너의 x 버튼을 클릭했을 때)를 나타내는 상태값을 리턴한다. 리턴될 수 있는 가능한 상태는CANCEL_OPTION,APPROVE_OPTION, 혹은ERROR_OPTION와 같은 클래스 상수에 의해 지정된다.JFileChooser의 예제를 보자.

import java.io.File;   import javax.swing.*;   public class Basics {     public static void main(String args[]) {       SwingUtilities.invokeLater(new Runnable() {         public void run() {           JFileChooser fileChooser =                  new JFileChooser(".");           int status = fileChooser.showOpenDialog(null);           if (status == JFileChooser.APPROVE_OPTION) {             File selectedFile =                   fileChooser.getSelectedFile();             System.out.println("Selected: "                     + selectedFile.getParent()                     + " --- "                     + selectedFile.getName());           }           System.exit(0);         }       });     }   }

이 프로그램은 파일 선택창 다이알로그를 디스플레이한다. 사용자가 디렉토리와 파일을 선택하면 다이알로그는 디렉토리를 인식하고 파일이름을 디스플레이한다.

사용자 삽입 이미지

단일/다중 선택

JFileChooser는 단일 선택 모드를 디폴트 값으로 한다. 이는 사용자가 한번에 하나의 디렉토리나 파일만 선택할 수 있다는 것을 의미한다. 만약 한번에 여러 개의 항목을 선택할 수 있는 것을 허용한다면,multiSelectionEnabled를 true로 설정해야 한다. 예제를 보자.

import java.io.File;   import javax.swing.*;   public class Multi {     public static void main(String args[]) {        SwingUtilities.invokeLater(new Runnable() {          public void run() {            JFileChooser fileChooser                    = new JFileChooser(".");            fileChooser.setMultiSelectionEnabled(true);            int status = fileChooser.showOpenDialog(null);            if (status == JFileChooser.APPROVE_OPTION) {                   File selectedFiles[] =                         fileChooser.getSelectedFiles();               for (int i=0,                     n=selectedFiles.length; i<n; i++) {                         System.out.println("Selected: "                          + selectedFiles[i].getParent()                          + " --- "                          + selectedFiles[i].getName());               }            }            System.exit(0);          }       });     }   }

selection set을 검색하기 위해서는getSelectedFile()가 아닌getSelectedFiles()를 사용해야 한다는 것을 기억하자.

 

사용자 삽입 이미지

 

J2SE SDK version 1.4이전에는, 모든 룩앤필이 다중 선택을 지원하지 않았지만 현재는 모든 시스템이 제공하는 룩앤필을 다중 선택에 사용할 수 있다.

파일과 디렉토리의 선택

일반적으로 사용자는 파일 선택창를 이용해서 파일을 선택하지만, 디렉토리를 선택할 수 있도록 할 수도 있다. 간단하게setFileSelectionMode메소드를 호출하면 된다. 다만 호출시 다음 상수 중의 하나를 지정해야 한다.

  • JFileChooser_ONLY
  • JFileChooser.DIRECTORIES_ONLY
  • JFileChooser_AND_DIRECTORIES

각각의 상수는 파일 선택창를 위한 모드를 지정한다. 예를 들면,JFileChooser_AND_DIRECTORIES상수는 파일 선택창에서 파일이나 디렉토리 모두 선택가능 하도록 설정한다. 다시 말하면, 사용자가 동일한 선택창에서 파일이나 디렉토리를 선택할 수 있다는 말이다.

사용자는 디렉토리를 선택할 때 다중 선택을 할 수 있다. 이는 하나의 선택창에서 여러 개의 디렉토리를 선택할 수 있다는 것을 말한다. 다음 프로그램이 이를 나타낸다.

-----------------------------------------------------------------------------------

import java.io.File;   import javax.swing.*;   public class Dirs {     public static void main(String args[]) {       SwingUtilities.invokeLater(new Runnable() {         public void run() {           JFileChooser fileChooser =                   new JFileChooser(".");           fileChooser.setMultiSelectionEnabled(true);           fileChooser.setFileSelectionMode(                  JFileChooser.DIRECTORIES_ONLY);           int status = fileChooser.showOpenDialog(null);           if (status == JFileChooser.APPROVE_OPTION) {             File selectedFiles[] =                  fileChooser.getSelectedFiles();             for                (int i=0, n=selectedFiles.length; i<n; i++) {                     System.out.println("Selected: "                         + selectedFiles[i].getParent()                         + " --- "                         + selectedFiles[i].getName());             }           }           System.exit(0);         }       });     }   }------------------------------------------------------------------------
사용자 삽입 이미지

디렉토리 선택 모드에서, File Name 부분에 나타나는 최초의 텍스트는 현재 선택된 디렉토리이다. 파일 선택 모드에서는 이 필드는 비어있다.

File Filters

파일 필터는 선택창에서 선택될 수 있는 파일을 제한한다. 가령, 사용자가.java소스 파일만을 보기를 원한다면,.java확장자만을 위한 파일 필터(FileFilter클래스의 서브클래스)를 형성할 수 있다. 디폴트 파일 필터는 파일 선택창에 있는 모든 파일을 열거하는 "accept all"로 설정되어 있다. 선택창에 파일 필터를 추가하면, 그 필터는 적절한 드롭 다운 리스트에 나타나게 된다. 선택창의 Motif 버전에서는 Folders 리스트의 윗부분에, Windows 와 Metal 버전에서는 윈도우의 하단부에 위치한다.

파일 필터를 파일 선택창에 추가하기 위해서는,javax.swing.filechooser패키지에서FileFilter인스턴스를 생성해야 한다. 그리고는 새로운 필터를 입력한addChooseableFileFilter메소드를 호출한다. 그러면 이 필터는 드디어 드롭 다운 필터 리스트에서 이용 가능하게 된다. 혹은setFileFilter메소드를 호출해서 필터를 선택할 수도 있다. 이 경우, 선택창이 최초로 디스플레이될 때, 'all' 옆에 필터 세트를 볼 수 있다. 파일 필터를 명시적으로 설정하지 않았다면 마지막으로 추가된 것이 최초 선택값이다.

JFileChooser를 위한 파일 필터와 Java I/O 패키지의 필터를 혼동하지 말자. 이름이 동일하긴 하지만, 그것들의 패키지와 사용법은 다르다.

다음Filters프로그램은 파일 필터의 사용을 보여준다. 프로그램을 실행하기 위해서는 SDK 데모에 포함된ExampleFileFilter클래스가 필요하다. SDK의demo/jfc/FileChooserDemo/src디렉토리를 살펴보자.( 윈도우에서는 물론 역슬래쉬를 사용해야 한다. )ExampleFileFilter클래스는 모든 형식의 확장자를 위한 필터를 생성할 수 있게 해준다. 적절한 파일 확장자를 추가하고, 선택창에 각각의 필터를 추가하자.

------------------------------------------------------------------------

import java.io.File;   import javax.swing.*;   public class Filters {     public static void main(String args[]) {       SwingUtilities.invokeLater(new Runnable() {         public void run() {           JFileChooser fileChooser =                   new JFileChooser(".");           ExampleFileFilter filter =                   new ExampleFileFilter("java");           filter.setDescription("Java Source Files");           fileChooser.addChoosableFileFilter(filter);           filter = new ExampleFileFilter("class");           filter.setDescription("Class Files");           fileChooser.addChoosableFileFilter(filter);           filter = new ExampleFileFilter("java");           filter.addExtension("class");           filter.setDescription("Source and Class Files");           fileChooser.addChoosableFileFilter(filter);           int status = fileChooser.showOpenDialog(null);           if (status == JFileChooser.APPROVE_OPTION) {             File selectedFile =                     fileChooser.getSelectedFile();             System.out.println("Selected: "                     + selectedFile.getParent()                     + " --- "                     + selectedFile.getName());           }           System.exit(0);         }       });     }   }--------------------------------------------------------------------------
사용자 삽입 이미지
 
 

액세서리 패널

JFileChooser의 더욱 재미있는 특징은 그것의 액세서리 패널에 있다. 액세서리 패널에는 현재 선택값에 관련된 정보를 보여주는 컴포넌트가 위치할 수 있다. 가령, 현재 선택값이 이미지 타입이라면 컴포넌트는 이미지 프리뷰어가 될 수 있고, 오디오 파일이라면 사운드 플레이어가 될 수 있다. 파일 선택에서 값이 바뀔 때마다 다른 정보가 액세서리 패널에 연결된다.

액세서리 패널을 만들기 위해서는, 적절한 컴포넌트를 생성하고setAccessory를 호출해서 그 컴포넌트를JFileChooser에 첨가해야 한다. 액세서리 패널은PropertyChangeListener로서JFileChooser에 첨부한다. 주목해야 할 속성은SELECTED_FILE_CHANGED_PROPERTY이다.SELECTED_FILE_CHANGED_PROPERTY의 속성이 바뀌면, 액세서리 컴포넌트는 그것의 상태를 변경할 수 있다.

예제를 보자. 다음LabelAccessory는 이미지 프리뷰어로 작동한다.

-------------------------------------------------------------------------

import javax.swing.*;   import java.beans.*;   import java.awt.*;   import java.io.*;   public class LabelAccessory extends JLabel           implements PropertyChangeListener {     private static final int PREFERRED_WIDTH = 125;     private static final int PREFERRED_HEIGHT = 100;     public LabelAccessory(JFileChooser chooser) {       setVerticalAlignment(JLabel.CENTER);       setHorizontalAlignment(JLabel.CENTER);       chooser.addPropertyChangeListener(this);       setPreferredSize(new Dimension               (PREFERRED_WIDTH, PREFERRED_HEIGHT));     }        public void propertyChange(       PropertyChangeEvent changeEvent) {        String changeName =           changeEvent.getPropertyName();        if (changeName.equals            (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {                File file = (File)changeEvent.getNewValue();                if (file != null) {                        ImageIcon icon =                         new ImageIcon(file.getPath());                if (icon.getIconWidth()                     > PREFERRED_WIDTH) {                        icon = new ImageIcon(                        icon.getImage().getScaledInstance                        (PREFERRED_WIDTH, -1,                          Image.SCALE_DEFAULT));                if (icon.getIconHeight()                     > PREFERRED_HEIGHT) {                        icon = new ImageIcon(                        icon.getImage().getScaledInstance                        (-1, PREFERRED_HEIGHT,                          Image.SCALE_DEFAULT));                }          }          setIcon(icon);         }       }     }   }

마지막으로, 다음Accessories프로그램을 실행시켜 보자. 이를 실행하면 액세서리 패널을 볼 수 있다. 프로그램을 실행할 때, 이미지를 포함하는 디렉토리를 선택해야 한다는 것을 잊지 말자. 프리뷰 패널에서 이미지를 볼 수 있다. 현재 선택값이 이미지가 아니면 프리뷰 패널에는 아무것도 나타나지 않는다.

import java.io.File;   import javax.swing.*;   public class Accessories {     public static void main(String args[]) {       SwingUtilities.invokeLater(new Runnable() {         public void run() {           JFileChooser fileChooser =                  new JFileChooser(".");           LabelAccessory accessory =                  new LabelAccessory(fileChooser);           fileChooser.setAccessory(accessory);           fileChooser.addPropertyChangeListener               (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY,                 accessory);           int status = fileChooser.showOpenDialog(null);           if (status == JFileChooser.APPROVE_OPTION) {             File selectedFile =                     fileChooser.getSelectedFile();             System.out.println("Selected: "                     + selectedFile.getParent()                     + " --- "                     + selectedFile.getName());           }           System.exit(0);         }       });     }   }--------------------------------------------------------------------
사용자 삽입 이미지
 
 

FileView

파일 이름이 열거되어 있는 파일 선택창 내의 영역은 추상 클래스FileView에 의해 조정된다. 커스텀 서브클래스를 생성함으로써 파일을 열거하는 방법을 사용자 정의할 수 있다. 이 클래스는 아이콘이나 이름을 찾기 위한 5개의 메소드를 갖지만, 속성을 모두 사용자 정의할 필요는 없다. 메소드 중의 하나라도 null값을 리턴하면, 컴포넌트는 디폴트 값을 찾아내기 위해 룩앤필의 특정한 속성을 컴토하게 된다.

이를 실행시킬 때에는 자바 관련 파일들, 즉.java files에는 파란색 아이콘,.class files에는 초록색 아이콘과 같은 특별한 아이콘들을 만들기 위해JFileChooser를 생성해야 한다. .java 파일에는 파일 이름에 파일 사이즈를 덧붙이자.

아이콘을 정의하고 있는 예제이다.

-----------------------------------------------------------------------

import javax.swing.*;   import java.awt.*;      public class DiamondIcon implements Icon {     private Color color;     private boolean selected;     private int width;     private int height;     private Polygon poly;     private static final int DEFAULT_WIDTH = 10;     private static final int DEFAULT_HEIGHT = 10;     public DiamondIcon(Color color) {             this(color, true, DEFAULT_WIDTH,                   DEFAULT_HEIGHT);     }     public DiamondIcon(Color color, boolean selected) {             this(color, selected, DEFAULT_WIDTH,                   DEFAULT_HEIGHT);     }     public DiamondIcon(Color color, boolean selected,                         int width, int height) {       this.color = color;       this.selected = selected;       this.width = width;       this.height = height;       initPolygon();     }     private void initPolygon() {       poly = new Polygon();       int halfWidth = width/2;       int halfHeight = height/2;       poly.addPoint(0, halfHeight);       poly.addPoint(halfWidth, 0);       poly.addPoint(width, halfHeight);       poly.addPoint(halfWidth, height);     }     public int getIconHeight() {       return height;     }     public int getIconWidth() {       return width;     }     public void paintIcon(      Component c, Graphics g, int x, int y) {       g.setColor(color);       g.translate(x, y);       if (selected) {         g.fillPolygon(poly);       } else {         g.drawPolygon(poly);       }       g.translate(-x, -y);     }   }

위와 같은 특별한 아이콘들을 보여주는JFileChooser를 생성하는 프로그램이다. 원한다면 디폴트 속성을 보기 위해setFileView라인을 코멘트처리할 수 있다. 그리고 파란색과 초록색 아이콘을 이용해서 사용자 정의된FileView를 볼 수 있도록 코멘트를 다시 활성화 시킬 수 있다.(이 때 사용자의 위치는 소스와 컴파일 된 소스 파일을 포함하는 디렉토리 안으로 가정한다.)

import java.io.File;   import java.awt.*;   import javax.swing.*;   import javax.swing.filechooser.*;   public class JavaFileView extends FileView {     Icon javaIcon = new DiamondIcon(Color.blue);     Icon classIcon = new DiamondIcon(Color.green);     /**      * If .java file, add length to name      */     public String getName(File file) {       String filename = file.getName();       if (filename.endsWith(".java")) {               filename += " : " + file.length();               return filename;       }       return null;     }     /**      * Return special icons for .java and .class files      */     public Icon getIcon(File file) {       // default icons for all directories       if (file.isDirectory()) {               return null;       }       String filename = file.getName();       if (filename.endsWith(".java")) {               return javaIcon;       } else if (filename.endsWith(".class")) {         return classIcon;     }     return null;     }     public static void main(String args[]) {       SwingUtilities.invokeLater(new Runnable() {         public void run() {           JFileChooser fileChooser =                   new JFileChooser(".");           FileView view = new JavaFileView();           fileChooser.setFileView(view);           int status = fileChooser.showOpenDialog(null);           System.exit(0);         }       });     }   }

'Programming > JAVA' 카테고리의 다른 글

[펌] 생성자와 THIS  (0) 2005.08.18
[펌] Properties 예제  (0) 2005.07.11
[펌] 서버 소켓 예제  (0) 2005.06.24
[펌] 클라이언트 소켓  (0) 2005.06.24
[펌] 13. 쓰레드(Thread)  (0) 2005.06.23

Posted by 영웅기삼
,