반응형

JComboBox에서 선택된 값을 리턴하는 메소드를 찾아보니 없는거 같다.

별것 아닌거 같지만 이런게 없어 하는 의아한 생각이 든다.

다른메소드를 이용하여 가져오는게 가능하니 만들지 않았을 수도 있지만

이러한 경우는 많이 사용하기 때문에 있는것이 당연하지 않나 하는 의문이 든다.

므튼 메소드가 없기 때문에(내가 찾지 못했을 수도?) 방법을 정리해보자.

나중에 까먹고 그 메소드를 찾기위해 API를 또 찾기 때문에 (있을텐데 ?? 하면서 )

jcombo.getSelectedItem().toString()

jcombo.getItemAt(jcombo.getSelectedIndex()).toString()

반응형

Sun Developer Network 공식 블로그 <출처 : http://blog.sdnkorea.com/blog/239 >

대부분의 경우 개발자들은 자바 애플리케이션이 배포된 플랫폼에 딱 맞는 애플리케이션처럼 보이기를 원한다. Mac OS X와 같은 몇몇 플랫폼에서는 적절한 룩앤필이 디폴트값으로 정해지는 반면에 윈도우와 같은 플랫폼은 특정 룩앤필(look and feel)을 설정하기 위해서 다음과 같은 호출이 필요하다.

   UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());

이번 테크팁에서는 탑재된 룩앤필을 플랫폼에 맞도록 결정하게 될 것이다. 새로이 이용 가능한 GTK+ 룩앤필을 추가하고, 라디오 버튼을 클릭해서 룩앤필을 바꿀 수 있는 애플리케이션을 만들게 될 것이다. 마지막으로, 애플리케이션에 사용자의 회사 마케팅 테마에 맞는 룩앤필을 적용하기 위해서 크로스 플랫폼 룩앤필을 사용자 정의하는 방법을 배우도록 하겠다.

인스톨된 룩앤필의 리스트를 생성하자. 정적 메소드 getInstalledLookAndFeels()를 호출하면 LookAndFeelInfo 타입의 객체의 배열을 리턴하게 된다. 인스톨된 LookAndFeels의 이름들을 배열로 얻어내려면 getName()를 이용하고, 구현된 각각의 클래스 이름을 알아내기 위해서는 getClassName()를 사용한다. 인스톨된 LookAndFeels의 이름을 배열로 디스플레이하는 다음 프로그램을 실행해 보자.

   import javax.swing.UIManager;

   public class AvailableLaF {
      public static void main(String[] args) {
        UIManager.LookAndFeelInfo[] installed =
          UIManager.getInstalledLookAndFeels();
        for (int i = 0; i < installed.length; i++) {
          System.out.println(installed[i].getName());
        }
        System.out.println(
          "\nThe current look and feel is "
          + UIManager.getLookAndFeel().getName());
      }
   }

솔라리스 운영환경이나 윈도우 2000에서 실행시켰다면 다음과 같은 출력 값을 보게 된다.

   Metal
   CDE/Motif
   Windows
   
   The current look and feel is Metal

Panther가 실행되는 Mac에서의 출력 값은 다음과 같다.

   Mac OS X
   Metal
   CDE/Motif

   The current look and feel is Mac OS X Aqua

J2SE 1.4.2에서는 GTK+ 2.0에 기반한 크로스 플랫폼 룩앤필도 존재한다. 크로스 플랫폼이 인스톨된 룩앤필의 리스트에 나타나지 않더라도, 이용 가능하다면 이를 인스톨할 수 있다. 크로스 플랫폼 룩앤필을 인스톨하기 위해서는 다음과 같은 메소드가 필요하다.

   private void installGTK() {
      try {
        String GTK =
          "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
        UIManager.setLookAndFeel(GTK);
        UIManager.installLookAndFeel("GTK", GTK);
      } catch (Exception e) {
        System.err.println("Could not install GTK");
      }
    }

GTK는 솔라리스나 Mac OS X와 같은 시스템에서 이용 가능하다. 윈도우에서는 "Could not install GTK" 과 같은 메시지를 보게 될 것이다. GTK를 지원하는 시스템에서 스윙 기반 프로그램을 실행하고자 한다면 커맨드 라인에서 룩앤필을 설정할 수도 있다. 다음은 룩앤필을 설정하는 커맨드 라인이다.

   java -Dswing.defaultlaf=
     com.sun.java.swing.plaf.gtk.GTKLookAndFeel 
     

이하의 프로그램 ChangingLaF는 라디오 버튼을 이용해서 룩앤필을 바꿀 수 있게 해준다. 만약 사용자의 시스템에서 GTK가 이용 가능하다면, 프로그램은 인스톨된 룩앤필의 리스트에 GTK를 추가하게 될 것이다. 그리고 나서 프로그램은 각각의 룩앤필을 위해 라디오 버튼을 생성하게 된다. 프로그램을 실행하고 라디오 버튼을 클릭하면 사용자 인터페이스는 지정한 룩앤필로 바뀌게 된다. 프로그램은 이너클래스의 actionPerformed() 메소드에 대한 응답으로 이를 실행하게 되는 것이다. 다음과 같은 2개의 과정이 수행된다.

   UIManager.setLookAndFeel(getText());
   SwingUtilities.updateComponentTreeUI(
     ChangingLaF.this);

룩앤필은 선택된 라디오 버튼의 텍스트 라벨로 바뀐다. 프로그램은 루트에 주어진 컴포넌트를 이용해서 트리를 새로 그리기 위해 updateComponentTreeUI()를 호출한다. updateComponentTreeUI()JFrame의 인스턴스인 객체를 호출하게 되는데, 이 때 JFrame 은 클래스 이름 뒤에 this가 붙은 형태로 식별된다. 위의 예제에서는, outer 클래스가 ChangingLaF이기 때문에 포함된 인스턴스는 ChangingLaF.this로 식별된다. 변경 가능한 룩앤필 옵션을 갖는 JFrame을 생성하기 위한 전체 ChangingLaF 프로그램을 보자.

   import javax.swing.JFrame;
   import javax.swing.JFileChooser;
   import javax.swing.JPanel;
   import javax.swing.UIManager;
   import javax.swing.JRadioButton;
   import javax.swing.ButtonGroup;
   import javax.swing.SwingUtilities;
   import javax.swing.UnsupportedLookAndFeelException;
   import java.awt.BorderLayout;
   import java.awt.GridLayout;
   import java.awt.event.ActionListener;
   import java.awt.event.ActionEvent;

   public class ChangingLaF extends JFrame {
      private static ButtonGroup group =
                                new ButtonGroup();

      public static void main(String[] args) {
        new ChangingLaF().getContentPane();
      }

      ChangingLaF() {
        JPanel myPanel = new JPanel();
        getContentPane().add(
          myPanel, BorderLayout.SOUTH);
        setLaFButtons(myPanel);
        getContentPane().add(new JFileChooser(),
          BorderLayout.CENTER);
        pack();
        setVisible(true);
      }

      private void setLaFButtons(JPanel choices) {
        installGTK();
        UIManager.LookAndFeelInfo[] laf =
          UIManager.getInstalledLookAndFeels();
        choices.setLayout(new GridLayout(laf.length, 1));
        for (int i = 0; i < laf.length; i++) {
          choices.add(new LaFButton(laf[i]));
        }
      }

      private void installGTK() {
        try {
          String GTK =
            "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
          UIManager.setLookAndFeel(GTK);
          UIManager.installLookAndFeel("GTK", GTK);
        } catch (Exception e) {
          System.err.println("Could not install GTK");
        }
      }

      private class LaFButton extends JRadioButton
        implements ActionListener {
        LaFButton(UIManager.LookAndFeelInfo laf) {
          super(laf.getClassName());
          group.add(this);
          addActionListener(this);
        }

       public void actionPerformed(ActionEvent event) {
         try {
           UIManager.setLookAndFeel(getText());
           SwingUtilities.updateComponentTreeUI(
             ChangingLaF.this);
           // call myFrame.pack() 
           // to resize frame for laf
         } catch (IllegalAccessException e) {
           // insert code to handle this exception
         } catch (UnsupportedLookAndFeelException e) {
           // insert code to handle this exception
         } catch (InstantiationException e) {
           // insert code to handle this exception
         } catch (ClassNotFoundException e) {
           // insert code to handle this exception
         }
       }
     }
   } 

ChangingLaF을 컴파일하고 실행해 보자. 플랫폼에 인스톨된 룩앤필을 쉽게 변경할 수가 있다. J2SE 1.4.2에서는 Windows XP 룩앤필도 적용할 수 있다.

사용자가 룩앤필을 사용자정의하고자 할 때가 종종 있다. 시스템이나 사용자 텍스트의 폰트를 바꾸거나, 컴포넌트를 해당 회사의 마케팅 테마에 맞는 색으로 그려야 하는 경우가 있다. 자, 룩앤필을 사용자 정의하고, 윈도우에서는 GTK가 지원되지 않는 관계로 Metal 테마를 이용하자. 이 예에서 사용하고 있는 DefaultMetalTheme는 J2SE 1.5에서는 더 이상 디폴트값으로 사용되지 않는다.

javax.swing.plaf.metal 패키지내의 클래스들을 살펴보자. MetalLookAndFeel 클래스는 Metal의 자바 구현(Java Implementation)이다. 서브클래스 DefaultMetalTheme는 기초적인 폰트 조절과, 메뉴 아이템, 시스템, 사용자 입력, 윈도우 타이틀 등을 변경하기 위해 사용된다. 이는 또한 3개의 원색과 3개의 2차 색으로 구별되는 6가지 기본 색을 변경하기 위해서도 쓰인다. 다음 CustomTheme프로그램은 DefaultMetalTheme의 서브 클래스를 생성한다. 이 프로그램은 접근 메소드들의 리턴값을 변경함으로써 오버라이드되는 색을 설정하는데, 이는 흰색을 파란색으로, 검은색을 빨강색으로 대체한다. 프로그램은 MetalLookAndFeel 클래스내의 setCurrentTheme() 메소드를 이용해서 이러한 비표준 색 테마를 선택하게 된다.

   import javax.swing.JFrame;
   import javax.swing.JFileChooser;
   import javax.swing.plaf.metal.MetalLookAndFeel;
   import javax.swing.UIManager;
   import javax.swing.UnsupportedLookAndFeelException;
   import javax.swing.plaf.metal.MetalLookAndFeel;
   import javax.swing.plaf.metal.DefaultMetalTheme;
   import javax.swing.plaf.ColorUIResource;
   import java.awt.Color;

   public class CustomTheme {

      public static void main(String[] args)
              throws UnsupportedLookAndFeelException{
        UIManager.setLookAndFeel(
          new MetalLookAndFeel());
        MetalLookAndFeel.setCurrentTheme(
          new CustomLaF());
        JFrame frame = new JFrame("Metal Theme");
        frame.getContentPane().add(new JFileChooser());
        frame.pack();
        frame.setVisible(true);
      }

      static class CustomLaF extends DefaultMetalTheme {
        protected ColorUIResource getPrimary1() {
          return new ColorUIResource(Color.MAGENTA);
        }

        public ColorUIResource getWhite() {
          return new ColorUIResource(Color.BLUE);
        }

        public ColorUIResource getBlack() {
          return new ColorUIResource(Color.RED);
        }

        public ColorUIResource getPrimaryControl() {
          return new ColorUIResource(Color.GREEN);
        }

        protected ColorUIResource getSecondary1() {
          return new ColorUIResource(Color.CYAN);
        }
      }
   }

변경된 테마를 보기 위해서는 Metal 룩앤필이 디폴트로 설정되었는지를 확인해 볼 필요가 있다. (윈도우에서는 필수적으로 확인해 보아야 한다.) 다음과 같이 커맨드 라인에서 애플리케이션을 실행할 수도 있다.

   java -Dswing.defaultlaf=
   javax.swing.plaf.metal.MetalLookAndFeel CustomTheme

스윙 룩앤필에 관한 자세한 정보는 자바 튜토리얼의 How to Set the Look and Feel를 참고하기 바란다.


반응형

Java 6 update10 에서 윈도우 Frame 투명화가 가능해졌네요.

이리저리 찾아보고 있었는데 자료를 찾았습니다. ㅎㅎ

원래 투명하게 보이는걸 좋아해서.. 내가 만든 플램도 넣고 싶었는데..

Java 라서 안되는구나.. 했는데 드디어 지원한다니 ㅋㅋ

영문 자료입니다.. 즐프 하시길..^^

How to Create Translucent and Shaped Windows

http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/

The article describes a feature that allows creating applications with translucent and shaped windows.

Contents
 
Introduction
Feature Overview
 
Translucent Windows
Shaped Windows
API Overview
Using the Feature
 
Determining the Support for a Desired Effect
Making a Window Translucent
 
Setting the Opacity Level of a Window
Enabling Per-Pixel Translucency
Setting the Opacity Level of a Window
Translucent and Shaped Windows Demo
Summary
 

JavaFX Script is a capable new language that offers a set of APIs for creating RIAs. It also provides you with access to the rich features of the the standard Java language. One of the major features introduced in the Java SE 6u10 release is the ability to create translucent and shaped windows. This includes:

  • making application windows translucent (tuning the general opacity of the window and using a per-pixel translucency effect)
  • setting shapes on application windows

This feature is available for objects of the java.awt.Window class and its descendants, for example javax.swing.JFrame, javax.swing.JFDialog, java.awt.Frame.

Translucent Windows
The translucent windows capability tunes the appearance of application windows using two different effects - simple translucency and per-pixel translucency. First, we will give an overview of the simple translucency effect. The simple translucency effect is used to make a window evenly translucent. When simple translucency is applied to a window, all the pixels of the window are assigned an alpha value which determines the level of opacity from the available range. The smaller the value, the more transparent the given window becomes. The minimum opacity level provides a completely transparent window, while the maximum opacity level represents a completely non-transparent (i.e. opaque) window. The following images demonstrate the use of the effect in four cases:

Dialog window without the effect applied Evenly translucent dialog window with opacity level 85%
Figure 1. Dialog window without the effect applied
Figure 2. Evenly translucent dialog window with opacity level 85%
Evenly translucent dialog window with opacity level 45% Evenly translucent dialog window with opacity level 25%
Figure 3. Evenly translucent dialog window with opacity level 45%
Figure 4. Evenly translucent dialog window with opacity level 25%
 

The screenshots are taken from the Translucent and Shaped Windows Demo. For details, see the Demo section. For more information about the effect and its use, see Setting the Opacity Level of a Window.

Another feature new to this release is the per-pixel translucency effect. Like simple translucency, per-pixel translucency can be used to make a window evenly translucent, though it is not recommended for performance reasons. However, it also enables you to control the opacity level of each individual pixel independently in order to make the window non-uniformly translucent or transparent. A good example of the use of the per-pixel effect is a gradient effect when the opacity "strength" of the window background increases from its top to the bottom. The following images show the per-pixel translucency effect in action for two cases:

The dialog window is evenly translucent using per-pixel alpha with 50% level
A gradient effect from fully translucent (upper left corner) to fully opaque
Figure 5. The dialog window is evenly translucent using per-pixel alpha with 50% level (note that the button remains opaque)
Figure 6. A gradient effect from fully translucent (upper left corner) to fully opaque (lower right corner) has been applied to the dialog window (note that the button remains opaque)
 

Note that when the per-pixel translucency effect is applied to make a window area transparent, the area may or may not remain clickable - this is a platform dependent behavior. For more information about the effect and its use, see Enabling Per-Pixel Translucency.

To sum up, the simple translucency effect is used to make a window evenly translucent or transparent, and the per-pixel translucency effect enables you to make a window evenly or non-uniformly translucent or transparent. Both the simple translucency and the per-pixel translucency can be used to make a window evenly translucent or transparent. However, when applied, the simple translucency effect consumes fewer system resources.

Shaped Windows
The other feature introduced in release 6u10 is the window shaping effect. Using shaping you can set any shape to an undecorated window. When the effect is applied, the desired area of a window becomes transparent. Thus, the combination of transparent and non-transparent pixels form the shape of a given window. The next images demonstrate window shaping in two cases:

Oval dialog window
Rounded rectangle dialog window
Figure 7. Oval dialog window
Figure 8. Rounded rectangle dialog window
 

Note that transparent areas of the window become unclickable. For more information about the effect and its use, see Setting the Shape of a Window.

These effects can be applied in combination. For example, you can create an oval shaped translucent window or a rounded rectangle window with the gradient effect applied:

Oval evenly translucent dialog window
Rounded rectangle dialog window with the gradient effect applied
Figure 9. Oval evenly translucent dialog window
Figure 10. Rounded rectangle dialog window with the gradient effect applied
 

Note that the effects may not be supported by the underlying platform (either because of hardware or software limitations or both). Therefore, before applying the effect, make sure that the platform supports it. For more details on system support, see Determining the Support for a Desired Effect.

The translucent and shaped windows feature is available through the new com.sun.awt.AWTUtilities class.

Note: the com.sun.awt.AWTUtilities class is not part of an officially supported API and appears as an implementation detail. The API is only meant for limited use outside of the core platform. It may change drastically between update releases, and it may even be removed or be moved in some other packages or classes. The class should be used via Java Reflection. Supported and public API will appear in the next major JDK release.

Method (* all the methods in the table are public and static)
Purpose
enum Translucency
Represents the kinds of translucency supported by the underlying system
boolean isTranslucencySupported(Translucency translucencyKind)
Returns if the given level of translucency is supported by the underlying system
void setWindowOpacity(Window window, float opacity)
Sets the opacity of a window
float getWindowOpacity(Window window)
Returns the opacity of a window
Shape getWindowShape(Window window)
Returns the shape of a window
void setWindowShape(Window window, Shape shape)
Sets the shape of a window
void setWindowOpaque(Window window, boolean isOpaque)
Enables the per-pixel translucency for a window
boolean isWindowOpaque(Window window)
Returns whether the window is opaque or translucent
boolean isTranslucencyCapable(GraphicsConfiguration gc)
Verifies whether a given graphics configuration supports the per-pixel translucency
 

Determining the Support for a Desired Effect
As already mentioned, the underlying system may not support the desired effect. That is why it is necessary to perform system support validation. The simple translucency and shaping effects require only general validation which indicates whether the system supports the effect in general.

To determine whether your system supports the effect, use the AWTUtilities.isTranslucencySupported() method passing a corresponding constant value as an argument. The constants PERPIXEL_TRANSPARENT, TRANSLUCENT, PERPIXEL_TRANSLUCENT represent shaping, simple translucency, and per-pixel translucency respectively. The next example shows how to determine whether your system supports simple translucency:

if (AWTUtilities.isTranslucencySupported(AWTUtilities.Translucency.TRANSLUCENT) {
      //perform translucency operations here
}
 

The per-pixel translucency also requires a window be created using a compatible graphics configuration. To check whether the given graphics configuration supports the per-pixel translucency effect use the isTranslucencyCapable() method. The following example shows how to determine whether the default graphics configuration supports per-pixel translucency:

if ((AWTUtilities.isTranslucencySupported(AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT)) &&
      (AWTUtilities.isTranslucencyCapable(defaultTranslucencyCapableGC))) {
      //perform translucency operations here
}
 

In case the default graphics configuration is not per-pixel translucency capable, you can go through all available graphics configurations and find one capable of translucency. Use the following code snippet:

GraphicsEnvironment env =
           GraphicsEnvironment.getLocalGraphicsEnvironment();
       GraphicsDevice[] devices = env.getScreenDevices();

     for (int i = 0; i < devices.length && translucencyCapableGC == null; i++) {          GraphicsConfiguration[] configs = devices[i].getConfigurations();          for (int j = 0; j < configs.length && translucencyCapableGC == null; j++) {              if (AWTUtilities.isTranslucencyCapable(configs[j])) {                  translucencyCapableGC = configs[j];              }          }      }

 

Once it has been determined that the system supports the desired effect, you can proceed to apply it to your top-level windows.

Making a Window Translucent
Setting the Opacity Level of a Window
The general opacity level of the application window is controlled by the the setWindowOpacity method. This method takes window and opacity variables as arguments. The window argument defines the window to apply the effect to. This argument must be an instance of the java.awt.Window class or its descendant, such as javax.swing.JFrame. The opacity argument is responsible for the level of opacity of the window. The lower its value, the more transparent the window becomes. The range of allowed values is [0f ; 1f]. If you set the value to 0f, the window becomes completely transparent (i.e. invisible). If the value is set to 1f, then the window becomes completely opaque (which is equal to a case when the effect is not applied at all). If the opacity level value is out of the range, it throws an IllegalArgumentException. Note that the effect can not be applied to full-screen windows. If you are in full screen windows mode and the opacity value is lower than 1f, you will get an IllegalArgumentException.

The following code snippet shows how to set the opacity level for your window. To make the window translucent, the example uses the setWindowOpacity method via Java Reflection, passing window and 0.75f as arguments. Window is an instance of the JFrame class, 0.75f is the value of the translucency.

Note that all the examples from this article that use the AWTUtilities class should be implemented via Java Reflection API.

try {
   Class<?> awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities");
   Method mSetWindowOpacity = awtUtilitiesClass.getMethod("setWindowOpacity", Window.class, float.class);
   mSetWindowOpacity.invoke(null, window, Float.valueOf(0.75f));
} catch (NoSuchMethodException ex) {
   ex.printStackTrace();
} catch (SecurityException ex) {
   ex.printStackTrace();
} catch (ClassNotFoundException ex) {
   ex.printStackTrace();
} catch (IllegalAccessException ex) {
   ex.printStackTrace();
} catch (IllegalArgumentException ex) {
   ex.printStackTrace();
} catch (InvocationTargetException ex) {
   ex.printStackTrace();
}
 

When applied, the method makes the frame translucent with a 75% level of opacity.

To get the current opacity of a window, use the getWindowOpacity method passing a window object as its argument. If the opacity level has not yet been set, this method returns 1.0f. In case the method returns 0f, the window is completely transparent. The next code snippet shows how to get the current level of opacity of a window:

float opacity = AWTUtilities.getWindowOpacity(frame);
 

Enabling Per-Pixel Translucency
The setWindowOpaque method is used to enable per-pixel alpha support for the given window. The method takes the window and isOpaque variables as arguments. The window argument defines the window you apply the effect to. Note that the argument must represent a window created using an effect compatible graphics configuration. For more information on graphics configurations, see Determining the Support for a Desired Effect. Also note that the window must not be in full-screen mode when making it non-opaque, or an IllegalArgumentException is thrown.

The isOpaque parameter defines whether the window must be opaque (true), or translucent (false). Once the window becomes non-opaque (the isOpaque is set to false), the drawing sub-system starts to respect the alpha value of each individual pixel. If a pixel gets painted with an alpha color component equal to zero, it becomes visually transparent; if the alpha of the pixel is equal to 255, the pixel is fully opaque. Interim values of the alpha color component make the pixel semi-transparent (i.e. translucent). The following code snippet shows how to enable the per-pixel alpha support for your window.

AWTUtilities.setWindowOpaque(frame, false);
 

If invoking the getWarningString on the window object returns a non-null String, this method will not affect the opacity of the window.

The following code snippet shows how to achieve the gradient effect. It is done by defining the parameters of the JPanel component using the GradientPaint method:

jPanel1 = new javax.swing.JPanel() {
      protected void paintComponent(Graphics g) {
          if (g instanceof Graphics2D) {
              final int R = 240;
              final int G = 240;
              final int B = 240; 

            Paint p =             new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0),                 getWidth(), getHeight(), new Color(R, G, B, 255), true);             Graphics2D g2d = (Graphics2D)g;             g2d.setPaint(p);             g2d.fillRect(0, 0, getWidth(), getHeight());      } else {     super.paintComponent(g);      }    }  }

 

Then the component should be placed on the frame:

frame.add(jPanel1);
 

Setting the Shape of a Window
To apply a shape to a window use the setWindowShape method. The method uses the window argument to define the window you want to set the shape to. Additionally, it uses the shape argument to define the desired shape. The shape can be any instance of the java.awt.Shape interface, for example, Ellipse2D.Float or RoundRectangle2D.Float. The next code snippet shows how to set an oval shape on your window. In the example, the fd argument represents the JFrame window, Ellipse2D.Float creates a new instance of an Ellipse2D object that defines the shape of the window:

fd.addComponentListener(new ComponentAdapter() {
     @Override
     public void componentResized(ComponentEvent evt) {
       Shape shape = null;
       shape = new Ellipse2D.Float(0, 0, fd.getWidth(), fd.getHeight());
       AWTUtilities.setWindowShape(fd, shape);
     }
});
 

It is recommended to set the shape using the componentResized() method as this enables precise control of the shape according to the current size of the window.

When setting the shape on your window, note that the effect supports only undecorated windows. If your window is decorated and you apply the effect, you will get the original shape of the window without the effect applied to it. If the window has been created by untrusted code (i.e. the window has a non-null warning string returned by getWarningString()), the method returns without affecting the shape of the window. Also note that the window must not be in the full-screen mode when setting a non-null shape. Otherwise, an IllegalArgumentException is thrown.

To get the current value of the shape of a window, use the getWindowShape method passing a window as an argument. The getWindowShape method returns an object that implements the shape interface and represents the shape previously set . If no shape has been set yet, or the shape has been reset to null, this method returns null. In other words, the default rectangular shape is displayed when the null argument is passed. The following code demonstrates how to get the current shape of the window:

Shape currentShape = AWTUtilities.getWindowShape(frame);
 

You can see the translucency and shape features in action by running the "TranslucencyShapeDemo" example. Click the Launch button to run Demo using Java Web Start. Note that in order to start the demo you must have JDK 6u10 or later installed and properly configured on your machine. You can download release 6u10 at the java.sun.com download page.

The application enables you to choose a desired effect or a combination of effects and apply it to an undecorated dialog window. The application interface contains the following elements: a slidebar to set the level of constant alpha for the simple translucency effect from the range [0% ; 100%], three radio buttons to set the shape of a window - rectangular, with rounded corners, or oval, a check box to enable or disable the per-pixel gradient effect, Paint Gradient check box to switch the per-pixel gradient effect on and off, Display/Hide the frame and Close the Application buttons. Once the settings are defined, click the Display the frame button to display the dialog window with the desired effect applied. Note that you can also change the effect spontaneously. To do so, choose an effect type when the window is displayed, the window will automatically switch its view. The dialog window itself contains the Reshape Me button. When clicked, the window randomly changes its size and location on the desktop. To hide the dialog window, click Hide the frame, to close the application, click Close the Application button.

Launches the TranslucentShapes application

You can find the entire code for this program in ControlFrame.java, FancyFrame.java, Main.java, and AWTUtilitiesWrapper.java, all of which are packed in the TranslucentShapes NetBeans project. Note that the application uses the Java Reflection API. The Reflection mechanism is implemented through the AWTUtilitiesWrapper class. You can download the TransclucentShapes NetBeans project as a zip file.

This article provides a description of the translucent and shaped windows feature. It includes an overview, discusses the feature API, and offers practical examples. The demo attached to the article shows the use of each featured effect individually as well as the use of the effects in combination.

반응형

우아한 Metal 룩앤필의 Swing이 처음 모습을 드러냈을 때, 미적인 면에서 그 주된 경쟁 상대는 Windows 95 인터페이스였습니다. 약 10년 전의 GUI 수준으로 볼 때 Metal은 당시 일반적인 인터페이스에 비해 매력적이고 우아한 대안이었습니다.

자바 SE 5에서 업데이트된 Ocean 테마는 Metal이 지금까지도 선택 받는 데 기여했으나, 이제는 플랫폼을 넘나드는 Swing의 외관을 전면적으로 개편해야 할 시점입니다.

Nimbus 룩앤필의 세계로 오십시오. Synth에 기반한 새롭고 현대적인 룩앤필의 Nimbus는 애플리케이션에 매우 세련된 느낌을 부여합니다. 또한 Nimbus는 정적 비트맵이 아니라, 온전히 Java 2D 벡터 그래픽을 이용해서 만들어졌기 때문에 크기가 매우 작고(불과 56KB!), 임의의 해상도에서 렌더링이 가능합니다.

사용자 삽입 이미지

그림 3: Metal 테마의 SwingSet3
 
사용자 삽입 이미지


그림 4: Nimbus 테마의 SwingSet3
 

호환성 때문에 Metal은 여전히 Swing의 기본 룩앤필이지만 애플리케이션에서 Nimbus를 사용하도록 업데이트하는 작업은 너무나 간단합니다. 즉, 코드 한 줄로 충분합니다.

UIManager.setLookAndFeel("com.sun.java.swing.plaf..nimbus.NimbusLookAndFeel");

또한 명령줄에 -Dswing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel을 추가하면 Nimbus를 기본 룩앤필로 지정할 수 있습니다. 보다 영구적으로 이 속성을 설정하려면 다음과 같은 코드를

swing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel

<JAVA_HOME>/lib/swing.properties 파일에 추가합니다. swing.properties 파일이 없으면 새로 만들어야 합니다.

Nimbus에 관한 더 자세한 정보는 Nimbus early access 페이지를 참고하십시오.



이 글의 영문 원본은
Nimbus Look and Feel in Java SE 6 Update 10 Beta
에서 보실 수 있습니다.

반응형

JFileChooser는 사용자로 하여금 읽어들일 파일이나 저장할 파일을 선택하도록 도와주는 선택창이다. JFileChooser는 아래의 그림처럼 FileSystemView, FileView, FIleFileter 그리고 Accessory등과 같은 복합적인 구조로 되어 있다.(아래의 그림에서는 Accessory는 보이지 않음)

 

파일을 선택하기 위해서 사용되는 대표적인 메소드는 showOpenDialog(), 와 showSaveDialog()를 사용한다.

창이 열리고 "열기"버튼이나 "저장"버튼을 클릭하게되면 APPROVE_OPTION이 반환되고, 취소 버튼을 클릭하게 되면 CANCEL_OPTION 이 반환된다.

 

선택한 파일에 대한 정보는 getSelectedFile()메소드를 사용하므로 알 수 있다.

 

 

[주요생성자]

JFileChooser() 사용자의 홈 디렉토리를 가리키는 창을 만든다.
JFileChooser(File dir)
JFileChooser(String dir)
주어진 dir을 가리키는 창을 만든다.

 

 

[ 기본 설정 관련 주요메소드]

void setCurrentDirectory(File dir) 현재 사용 디렉토리를 지정한다.
void setDialogTitle(String title) 창의 제목을 정한다.
void setApproveButtonText(String txt) 열기 또는 저장 버튼의 텍스를 지정한다.

 

 

[대화창 관련 주요 메소드]

int showOpenDialog(Component parent) 열기용 창을 만든다.
int showSaveDialog(Component parent) 저장용 창을 만든다.

이때 반환값 int는 JFileChooser.APPROVE_OPTION 또는 JFileChooser.CANCEL_OPTION 값을 반환한다.

 

 

[파일 선택관련 주요 메소드]

void setFIleSelectionMode(int mode)

파일 선택 모드를 정한다.

  • JFileChooser.FILES_ONLY : 파일만 선택 가능
  • JFileChooser.DIRECTORIES_ONLY : 디렉토리만 선택 가능
  • JFileChooser.FILES_AND_DIRECTORIES : 파일과 디렉토리 모두 가능
void setMultiSelectionEnabled(boolean b) 파일을 다중 선택하고자 할 때 사용한다.

void setSelectedFIle(File file)
void setSelectedFIles(File[] file)

주어진 파일을 선택 상태로 창을 생성한다.
File getSelectedFile()
FIle[] getSelectedFiles()
선택된 파일을 가져온다.

 

[컨트롤 관련 주요 메소드]

void addChoosableFileFilter(FileFilter filter) 파일 필터를 추가한다.
void setFileFilter(FileFilter filter) 파일 필터를 지정한다.
void setAccessory(JComponent accessory) 액세서리를 지정한다.
void setFileSystemView(FileSystemView fs) FIleSystemView를 지정한다.
void setFileView(FileView fv) FileView를 지정한다.

 

[사용예]

JDK 6.0
         JFileChooser chooser = new JFileChooser();
            FileNameExtensionFilter filter = new FileNameExtensionFilter(
                "JPG & GIF Images", "jpg", "gif");  //description,......확장자
            chooser.setFileFilter(filter);    //필터 셋팅
            int returnVal = chooser.showOpenDialog(parent);
            if(returnVal == JFileChooser.APPROVE_OPTION) {
               System.out.println("You chose to open this file: " +
                    chooser.getSelectedFile(). getName());
            }

JDK 6.0 이전버전

읽기창 만들기

  1.     public void fileOpen()
  2.     {
  3.         JFileChooser fc;
  4.         File fileName;
  5.         if(fileName !=null)
  6.         {
  7.             String dir = fileName.getAbsolutePath(); //현재 파일이 위치하는 디렉토리를 가져온다.
  8.             fc = new JFileChooser(dir);
  9.         }
  10.         else
  11.         {
  12.             fc = new JFileChooser();
  13.         }
  14.         
  15.         int yn = fc.showOpenDialog(this);
  16.         if(yn != JFileChooser.APPROVE_OPTION) return;
  17.         
  18.         fileName = fc.getSelectedFile();
  19.     }

저장창 만들기

  1.     public boolean fileSave()
  2.     {
  3.         File fileName;
  4.         JFileChooser fc = new JFileChooser();
  5.         int yn = fc.showSaveDialog(this);
  6.         
  7.         if(yn != JFileChooser.APPROVE_OPTION)
  8.         {
  9.              fileName = null;
  10.              return false;
  11.         }
  12.         
  13.         fileName = fc.getSelectedFile();
  14.         
  15.         this.setTitle("MyEditor[" + fileName + "]");
  16.         
  17.         return true;
  18.     
  19.     }

파일 필터 만들기

먼저 아래와 같은 소스를 만들어 컴파일 한다.

  1. package classes;
  2. import java.io.*;
  3. class MyFilter extends javax.swing.filechooser.FileFilter
  4. {
  5.     String type;
  6.     String desc;
  7.     public MyFilter(String type, String desc)
  8.     {
  9.         this.type = type;
  10.         this.desc = desc;
  11.     }
  12.     public boolean accept(File f)
  13.     {
  14.         return f.getName().endsWith(type) || f.isDirectory();
  15.     }
  16.     
  17.     public String getDescription()
  18.     {
  19.         return desc;
  20.     }
  21. }

필터가 필요한 부분에서 아래 소스의 5,6행 처럼 원하는 필터를 지정하여 창을 열면 된다.

  1.         JFileChooser fc;
  2.         fc = new JFileChooser();
  3.         
  4.         // file filtering
  5.         fc.addChoosableFileFilter(new MyFilter(".txt","Text Files"));
  6.         fc.addChoosableFileFilter(new MyFilter(".java","Java Files"));

 

반응형
소프트웨어 사용자들은 결코 메뉴얼을 안본다. 아무리 어려운 프로그램이라 해도 사용자는 자기 스스로 방법을 찾아내려고 한다. 정말 혼자서 해결하지 못한다 해도 다른 사람에게 물어볼지언정 메뉴얼은 안본다.

따라서 개발자는 프로그램을 사용하기 쉽고 직관적으로 이용할 수 있도록 만들어야 한다. 결코 메뉴얼을 보지 않는 사용자들에게 어떻게 프로그램을 이해시키고 도움을 줄 수 있을지, 몇가지 방법을 알아보자.

사용자 가이드하기
가장 자주 쓰이는 방법은 각 인터페이스에 간단한 힌트나 길잡이 문구를 넣는 것이다. 스윙(Swing) 프레임워크는 툴팁 형태로 이러한 기능을 적용시키도록 해준다. setToolTipText 메소드를 호출함으로써 어떤 스윙 컴포넌트에 대해서도 툴팁을 설정할 수 있다.

툴팁이 설정되면 마우스가 해당 컴포넌트 위로 위치할 경우 텍스트로 된 간단한 설명이 작은 윈도우에 표시된다(마우스가 지나가면 사라진다). 이 설명에는 컴포넌트의 기능이나 개발자가 유용하다고 생각하는 정보 등이 담겨있다.

툴팁은 간결하고 명확한 방법이지만 단점도 있다. 아주 소량의 정보만 전달할 수 있으며, 인터페이스 위에 겹쳐져서 표시되기 때문에 오히려 사용에 방해가 되기도 한다. 따라서 프로그램의 메뉴에 사용하기에는 적합하지 않은 면이 있다.

툴팁 외에 상태표시줄에 설명을 표시하는 방법이 있다. 기본 개념은 툴팁과 동일하다. 마우스가 어떤 요소 위에 있을 동안에만 설명이 나타난다. 다만 프로그램 윈도우의 상태표시줄에 설명이 보여지므로, 툴팁처럼 프로그램 사용에 방해가 되는 일은 없다.

마우스-오버 방식 적용하기
스윙에서는 상태표시줄에 설명을 보여주는 기능을 기본 제공되지 않지만, 어렵지 않게 직접 구현할 수 있다. 설명을 보여주고자 하는 각 항목을 '마우스 감지기(mouse listener)'와 연결하고, MouseListener 인터페이스의 mouseEntered와 mouseExited 메소드를 적용하면 된다.

mouseEntered 메소드는 설명을 보여주는 역할을, mouseExited 메소드는 설명을 사라지게 하는 역할을 한다. 이 이벤트 소스를 사용하면 항목을 식별해 자동으로 해당되는 설명을 보여주기 때문에 각 항목마다 일일이 마우스 연결을 하지 않아도 된다.

MouseOverHintManager(소스보기1)는 재사용이 가능한 상태표시줄 설명 기능을 보여준다. 사용법은 아주 간단하다. JLabel을 거치는 MouseOverHintManager의 인스턴스를 설정한 후, addHintFor 메소드를 호출해 각 항목에 대한 설명을 설정한다. 탑컨테이너(프로그램 창, 프레임, 대화상자 등)에 대해서 enableHints 메소드를 호출한다.

소스보기 1
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;


public class MouseOverHintManager implements MouseListener {
  private Map hintMap;
  private JLabel hintLabel;

  public MouseOverHintManager( JLabel hintLabel ) {
    hintMap = new WeakHashMap();
    this.hintLabel = hintLabel;
  }

  public void addHintFor( Component comp, String hintText ) {
    hintMap.put( comp, hintText );
  }

  public void enableHints( Component comp ) {
    comp.addMouseListener( this );
    if ( comp instanceof Container ) {
      Component[] components = ((Container)comp).getComponents();
      for ( int i=0; i<components.length; i++ )
       enableHints( components[i] );
    }
    if ( comp instanceof MenuElement ) {
      MenuElement[] elements = ((MenuElement)comp).getSubElements();
      for ( int i=0; i<elements.length; i++ )
       enableHints( elements[i].getComponent() );
    }
  }

  private String getHintFor( Component comp ) {
    String hint = (String)hintMap.get(comp);
    if ( hint == null ) {
      if ( comp instanceof JLabel )
       hint = (String)hintMap.get(((JLabel)comp).getLabelFor());
      else if ( comp instanceof JTableHeader )
       hint = (String)hintMap.get(((JTableHeader)comp).getTable());
    }
    return hint;
  }


  public void mouseEntered( MouseEvent e ) {
    Component comp = (Component)e.getSource();
    String hint;
    do {
      hint = getHintFor(comp);
      comp = comp.getParent();
    } while ( (hint == null) && (comp != null) );
    if ( hint != null )
      hintLabel.setText( hint );
  }

  public void mouseExited( MouseEvent e ) {
    hintLabel.setText( " " );
  }

  public void mouseClicked( MouseEvent e ) {}
  public void mousePressed( MouseEvent e ) {}
  public void mouseReleased( MouseEvent e ) {}
}


MouseOverHintManager를 적용하는 것도 상기한 절차와 유사하다. addHintFor 메소드는 변수로 컴포넌트 레퍼런스와 이에 대응하는 설명을 받고, 이를 맵(Map)에 저장한다. 설명은 WeakHashMap 인스턴스에 저장되기 때문에 대응 항목에 대한 참조가 더 이상 없을 경우 자동적으로 가비지-콜렉트(garbage-collected) 처리된다. 따라서 설명을 사라지게 하기 위한 별도의 메소드는 필요 없다.

enableHints 메소드는 변수인 탑컨테이너의 모든 항목, 하부항목, 메뉴요소 등에 대한 마우스 감지기로 MouseOverHintManager를 추가한다.

mouseEntered 메소드는 마우스 포인터가 항목을 가리키면 맵에서 해당되는 설명을 찾아 JLabel에 뿌려준다. mouseExited 메소드는 JLabel을 비워 설명을 제거한다.

트릭
상태표시줄 설명과 관련된 몇가지 간단한 트릭이 있다.

우선 mouseEntered 메소드는 ‘이벤트를 생성하는 항목’의 설명을 받는다는 점을 이용한다. mouseEntered는 해당 항목에 대응하는 설명이 없으면 상위 항목을 확인한다. 이 프로세스는 최상위 항목에 도달하거나 설명이 발견될 때까지 계속된다. 이 특성을 이용해 패널과 같은 하나의 컨테이너에 대해 하위 모든 요소들이 같은 설명을 공유하도록 하거나, 또는 상위 항목과 하위 항목에 대해 서로 다른 설명을 설정할 수 있다.

또다른 트릭은 getHintFor 메소드다. mouseEntered는 항목에 대한 설명을 받기위해 getHintFor를 호출한다. 그런데 변수로 넘겨받은 항목에 설명이 존재하지 않는 경우, getHintFor는 몇가지 특별한 경우를 체크한다. 문제의 항목이 JLabel, 또는 JTableHeader일 경우, getHintFor 메소드는 각각 JLabel이 붙여진 설명과 Jtable 설명을 리턴한다. 즉 항목과 라벨에 대해 별도로 두 번 설명을 설정할 필요가 없는 것이다. 각자 서로 다른 항목으로 보여지는 경우라도 마찬가지다.

설명을 넣자
MouseOverHintDemo(소스보기2)는 MouseOverHintManager 클래스 사용에 대한 간단한 예로, 상태표시줄이 있는 JFrame을 생성한다. 이 JFrame은 가장 흔히 사용되는 스윙 요소 및 설명을 보여준다.

소스보기 2
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;


class MouseOverHintDemo {
  public static void main( String[] args ) {
    JLabel hintBar = new JLabel(" ");
   MouseOverHintManager hintManager = new MouseOverHintManager(hintBar);
    JFrame frame = new JFrame("MouseOverHintDemo");
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
  
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("File");
    JMenuItem item1 = new JMenuItem("Load");
    JMenuItem item2 = new JMenuItem("Save");
    JMenuItem item3 = new JMenuItem("Exit");
  
    Box mainPanel = Box.createVerticalBox();
    JButton button = new JButton("Apply");
    JCheckBox checkBox = new JCheckBox("Disable hints");
    JLabel label = new JLabel("Backup strategy");
    JComboBox comboBox = new JComboBox(new String[] {"Always","Just the last","Never"});
    JFormattedTextField formattedText = new JFormattedTextField(new Date());
    Box radioPanel = Box.createVerticalBox();
    ButtonGroup radioGroup = new ButtonGroup();
    JRadioButton radio1 = new JRadioButton("left");
    JRadioButton radio2 = new JRadioButton("right");
    JTable table = new JTable(new String[][] {{"Copy","Ctrl+C"},{"Paste","Ctrl+V"},{"Cut","Ctrl+X"}}, new String[] {"Action","Shortcut"});
  
    hintManager.addHintFor( item1, "Loads a new file" );
    hintManager.addHintFor( item2, "Saves the current file" );
    hintManager.addHintFor( item3, "Exits the application" );
    hintManager.addHintFor( button, "Apply any changes made" );
    hintManager.addHintFor( checkBox, "Turns off the display of hints" );
    hintManager.addHintFor( comboBox, "Selects how many backups to make" );
    hintManager.addHintFor( formattedText, "Enters the date for next run" );
    hintManager.addHintFor( radioPanel, "Selects the position for application's toolbar" );
    hintManager.addHintFor( table, "Shortcuts for each application's action" );
  
    frame.setJMenuBar( menuBar );
    menuBar.add( menu );
    menu.add( item1 );
    menu.add( item2 );
    menu.add( item3 );
    frame.getContentPane().add( mainPanel, BorderLayout.CENTER );
    mainPanel.add( Box.createVerticalStrut(5) );
    mainPanel.add( button );
    mainPanel.add( Box.createVerticalStrut(5) );
    mainPanel.add( checkBox );
    mainPanel.add( Box.createVerticalStrut(5) );
    mainPanel.add( label );
    label.setLabelFor( comboBox );
    mainPanel.add( comboBox );
    mainPanel.add( Box.createVerticalStrut(5) );
   mainPanel.add( formattedText );
    mainPanel.add( Box.createVerticalStrut(5) );
    radioGroup.add( radio1 );
    radioGroup.add( radio2 );
    radioPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"Toolbar") );
    radioPanel.add( radio1 );
    radioPanel.add( radio2 );
    mainPanel.add( radioPanel );
    mainPanel.add( Box.createVerticalStrut(5) );
    mainPanel.add( table.getTableHeader() );
    mainPanel.add( table );
    mainPanel.add( Box.createVerticalStrut(5) );
    hintBar.setBorder( BorderFactory.createLoweredBevelBorder() );
    frame.getContentPane().add( hintBar, BorderLayout.SOUTH );
    frame.pack();
  
    hintManager.enableHints( frame );
    frame.setVisible( true );
  }
}


이 예제는 단순명료하다. 사용자 인터페이스의 모든 항목을 생성하고 이들에 대해 설명을 설정한 후 애플리케이션 윈도우를 만들고 ouseOverHintManager.enableHints를 호출한다. 유의할 점은 유저 인터페이스를 구성한 후에 끝으로 enableHints를 호출해야 enableHints가 모든 항목에 대한 마우스 감지기로 등록된다는 것이다. 이렇게 해야 MouseOverHintManager가 모든 항목의 마우스 이벤트를 접수해 각각에 해당하는 설명을 선택할 수 있다.

소스코드2 예제를 실행하면 몇가지 조절기능을 갖춘 간단한 윈도우가 뜬다. 항목과 메뉴 위로 마우스를 움직이면서 상태표시줄에 각각에 해당되는 설명이 나타나는지 확인해 보자. 2개의 라디오 버튼에 대해서는 같은 설명이 표시되는데, 이는 상위 패널에서 설명을 설정했기 때문이다.

기능에 대한 설명은 애플리케이션 사용을 쉽게 한다는 점에서 중요한 부분이다. 스윙 툴팁의 대안인 상태표시줄 설명 방법은 적용하기도 쉽다. 사용자들은 결코 메뉴얼을 보지 않기 때문에 프로그램을 사용하기 쉽고 직관적으로 이용할 수 있도록 만들어야 하는 것이 개발자들의 임무지만, 자바 GUI를 사용하는 경우라면 상기한 상태표시줄 설명이라는 간단한 도움기능을 넣을 수 있을 것이다. @
반응형
JTextField에서 숫자만 입력하는지 검사하기
현재(역주:2001년 11월 20일) 베타판이 나와있는 Java 2 SDK 표준에디션에는 양식에 맞는 텍스트 입력을 위해 JFormattedTextField 라는 컴포넌트가 추가되었다. 이 컴포넌트는 텍스트 필드에 입력된 것을 검사할 수 있다. 그러나 지금 당장 그것이 필요한데 정식판이 나올 때까지 기다릴 수 없다면 어쩌겠나? 텍스트 필드에 입력된 것을 검사할 수 있는 적어도 세가지의 다른 방법이 있다. 그 세가지는 키를 누르는 수준에서, 포커스 수준에서 그리고 데이터 모델 수준에서 검사할 수 있다. 이 팁은 숫자 입력만 받아들이는 텍스트 필드를 만들기 위해 이 기술들을 어떻게 사용하는 지를 보여줄 것이다.
AWT의 TextField에도 있는 것처럼, 스윙의 JTextField 컴포넌트에 KeyListener를 등록할 수 있다. 리스너가 등록되면, 키가 눌려지는 것을 알아낼 수 있다. 틀린 것을 수정하기 위해 backspace 키나 delete키 빼고는 숫자 키가 아니면 이것을 거부할 수 있다. 거부하는 것은 KeyEvent의 consume() 메소드를 호출함으로 처리된다. 이 메소드는 컴포넌트에게 그 키보드 입력은 입력 리스너에 의해 처리되었으니 화면으로 출력하지마라고 지시한다.
리스너를 사용해서 입력 검사하는 코드는 아래와 비슷할 것이다.
keyText.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if (!((Character.isDigit(c) ||
(c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE))) {
getToolkit().beep();
e.consume();
}
}
});

입력기(역주:한글입력기 같이 시스템에 설치된 IME)가 설치해야 되는 환경에서 동작한다면, 키 리스너를 사용하는 데 특별히 고려해야 할 것이 있다. 이 경우 입력기가 키 리스너가 키를 누르는 것을 감지 못하게 할 것이다. 이것은 보통 문자가 키보드키와 1:1로 메핑되지 않는 경우 생긴다. 예를들면 한자나 일본어를 입력할 경우에 그렇다.
KeyListener 대신에 FocusListener를 사용하면 약간 다른 동작을 한다. KeyListener는 키보드 키가 눌러지는 매번 확인하지만, FocusListener는 입력필드가 포커스를 잃을 때 검사한다. 필드값 전체를 검사하기 때문에 이 방법은 간단히 Integer의 parseInt() 메소드를 사용한다. 사실 입력값은 중요하지 않다. 중요한 것은 입력된 것을 파싱할 수 있다는 것이다.
FocusListner를 이용한 입력값 검사코드는 다음과 비슷할 것이다.
focusText.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
JTextField textField = (JTextField)e.getSource();
String content = textField.getText();
if (content.length() != 0) {
try {
Integer.parseInt(content);
} catch (NumberFormatException nfe) {
getToolkit().beep();
textField.requestFocus();
}
}
}
});

불행히도, 입력 화면에 메뉴가 있거나 팝업 대화상자가 있으면, 포커스 수준에서의 리스너를 사용하는 데는 문제가 있다. 메뉴를 사용할 때, 리스너는 top-level 메뉴가 입력 포커스를 받을 때, 실제 호출된다. 그리니까 선택하려는 메뉴를 찾아 이동할 때 실제 호출이 된다. 위의 리스너는 잘못된 입력에 대해 비프음을 낸다. 그러나 오류 메세지를 나타내기 위해 대화상자가 팝업되었다면 무슨 일이 일어날지를 상상해보라.
스윙 컴포넌트의 포커스 수준에서의 검사하는 두 번째 방법이 있다. InputVerifier를 컴포넌트에 붙일 수 있다. 이 추상 클래스는 boolean verify(JComponent) 메소드 하나를 가지고 있는데 입력값에 대해 검사를 수행하게 구현하면 된다. 이 메소드는 입력이 옳바르면 true를 반환하고 그렇지 않으면 false를 반환해야된다. FocusListener 기법에서처럼, true인지 false인지를 검사하기 위해 parseInt()를 사용해도 된다. 이 검사기를 붙이려면, setInputVerifier()를 호출하면된다. 사용자가 해당 필드를 벗어나 입력 포커스를 옮길 때 검사기는 입력값을 검사한다.
FocusListener의 경우에서처럼, InputVerifier는 각각의 입력이 유효한가를 결정하는 게 아니라 입력값 전체에 대해서 검사를 한다. 예를 들면, 이것은 입력값이 특정 범위 내에서 이뤄져야 하는 경우 중요하다. ??? [원문보기] As with the FocusListener, the InputVerifier permits validation on the whole field, versus trying to determine if part of the input is valid. This is important, for instance, if you want the input to be within a certain range.
InputVerifier에 잘못된 입력에 대해 어떻게 반응하는지를 기술하는 두번째 메소드 boolean shouldYieldFocus(JComponent)가 있다. 이 메소드는 기본적으로 verify()의 결과를 반환하게 구현되어 있다. 만약 잘못된 입력에 대해 비프음을 내고 싶다면, 그 값을 반환하기 전에 검사해야 된다.
InputVerifier를 사용해서 잘못된 입력에 대해 비프음을 내는 예제를 보자.
inputText.setInputVerifier(new InputVerifier() {
public boolean verify(JComponent comp) {
boolean returnValue = true;
JTextField textField = (JTextField)comp;
String content = textField.getText();
if (content.length() != 0) {
try {
Integer.parseInt(textField.getText());
} catch (NumberFormatException e) {
returnValue = false;
}
}
return returnValue;
}

public boolean shouldYieldFocus(JComponent input) {
boolean valid = super.shouldYieldFocus(input);
if (!valid) {
getToolkit().beep();
}
return valid;
}
});

이 세번째 방법은 입력 포커스를 다시 가져오기 위해 requestFocus()를 호출하지 않아도 되기 때문에 좀 깔끔하게 보이지만, 이것 역시 FocusListener와 같은 문제를 안고 있다.
이 팁에서 다루는 마지막 검증방법은 스윙의 모델-뷰-컨트롤러(MVC) 구조에 대한 이해를 수반한다. 모든 JTextComponent (JTextField 같은)은 이면에 데이터를 가진 텍스트 컴포넌트 모델이다. JTextField는 그 모델에 대해 단 한개의 뷰만 있다. 그 모델에 넣을 수 있는 것을 제한함으로써, JTextField에서 보여지는 것을 제한 할 수 있다.
데이터 모델에 입력 검사하는 것을 넣음으로써, 전에 언급된 메뉴를 선택되었을 때 무엇을 해야 하는 가하는 문제나 입력기(역주:IME) 리스너가 있을 때 입력을 검사하는 방법에 관한 문제는 피하게 된다. 이 마지막 검사 모델은 가장 복잡하지만 잘 동작한다.
JTextField의 기본 모델은 javax.swing.text.PlainDocument 클래스이다. 이 클래스는 사용자가 컴포넌트에 텍스트를 입력하거나 제거할 때 호출되는 insertString()와 remove() 메소드를 제공한다. 보통 한 번에 한 문자에 대해 행해진다. 그러나 오려내기나 복사하기가 수행될 때를 반드시 고려해야 된다. 각 메소드가 하는 것인 모델이 그 모델에 데이터가 추가되나 삭제되었을 때, 그것이 유효한가를 확인하는 것이다. 확인과정을 통과했다고 가정하면, super.insertString()이나 super.remove()를 호출해서 슈퍼클래스로 그 데이터를 전달한다.
insertString()의 핵심 부분은 대충 이렇하다. 입력된 것을 검정하기 위해서 어떤 것이 새 문자열이 될 것인가를 결정한다. 그 모델이 원래 비었다면 새 문자열은 입력된 값이다. 그렇지 않으면 새 값은 원래 있던 내용의 중간에 삽입된다. 새 값을 얻은 후, 그것을 Integer로 parseInt() 검사하고, 아무 문제 없으면, super.insertString()를 호출한다. 알아둘 것은 유효하지 않는 입력은 super.insertString()를 호출하지 않음으로써 그 입력이 거부되었음을 알린다. 문자열을 집어 넣지 않으면 아무것도 할 필요가 없다. 그러나 이 코드는 입력이 실패하면 비프음을 울린다.
String newValue;
int length = getLength();

if (length == 0) {
newValue = string;
} else {
String currentContent = getText(0, length);
StringBuffer currentBuffer = new StringBuffer(currentContent);
currentBuffer.insert(offset, string);
newValue = currentBuffer.toString();
}

try {
Integer.parseInt(newValue);
super.insertString(offset, string, attributes);
} catch (NumberFormatException exception) {
Toolkit.getDefaultToolkit().beep();
}

정수형 입력만 받아 들이는 모델의 경우, remove() 메소드의 기본 동작을 오버라이드할 필요는 없다. 정수형 텍스트 문자열에서 데이터(숫자)를 제거하고 숫자가 아닌 부분을 반환하는 것은 불가능하다. [원문보기] For the case of a model that only accepts integer input, it isn't necessary to override the default behavior of the remove() method. It is impossible to remove data from an integer text string and get back a non-integer.
완전한 모델을 정의한 후에, 그 모델을 텍스트 필드와 연결하기 위해 setDocument() 메소드를 사용해라.
modelText.setDocument(new IntegerDocument());

여기에 모든 네가지를 보여주는 완전한 예제가 있다. 이 안에 IntegerDocument 클래스의 정의도 볼 수 있을 것이다.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

public class TextInput extends JFrame {
JPanel contentPane;
JPanel jPanel1 = new JPanel();
FlowLayout flowLayout1 = new FlowLayout();
GridLayout gridLayout1 = new GridLayout();
JLabel keyLabel = new JLabel();
JTextField keyText = new JTextField();
JLabel focusLabel = new JLabel();
JTextField focusText = new JTextField();
JLabel inputLabel = new JLabel();
JTextField inputText = new JTextField();
JLabel modelLabel = new JLabel();
JTextField modelText = new JTextField();
IntegerDocument integerDocument1 =
new IntegerDocument();

public TextInput() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = (JPanel)getContentPane();
contentPane.setLayout(flowLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Input Validation");
jPanel1.setLayout(gridLayout1);
gridLayout1.setRows(4);
gridLayout1.setColumns(2);
gridLayout1.setHgap(20);
keyLabel.setText("Key Listener");
modelLabel.setText("Model");
focusLabel.setText("Focus Listener");
inputLabel.setText("Input Verifier");

keyText.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if (!(Character.isDigit(c) ||
(c == KeyEvent.VK_BACK_SPACE) ||
(c == KeyEvent.VK_DELETE))) {
getToolkit().beep();
e.consume();
}
}
});

focusText.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
JTextField textField = (JTextField)e.getSource();
String content = textField.getText();
if (content.length() != 0) {
try {
Integer.parseInt(content);
} catch (NumberFormatException nfe) {
getToolkit().beep();
textField.requestFocus();
}
}
}
});

inputText.setInputVerifier(new InputVerifier() {
public boolean verify(JComponent comp) {
boolean returnValue = true;
JTextField textField = (JTextField)comp;
String content = textField.getText();
if (content.length() != 0) {
try {
Integer.parseInt(textField.getText());
} catch (NumberFormatException e) {
getToolkit().beep();
returnValue = false;
}
}
return returnValue;
}
});

modelText.setDocument(integerDocument1);

contentPane.add(jPanel1);
jPanel1.add(keyLabel);
jPanel1.add(keyText);
jPanel1.add(focusLabel);
jPanel1.add(focusText);
jPanel1.add(inputLabel);
jPanel1.add(inputText);
jPanel1.add(modelLabel);
jPanel1.add(modelText);
}

public static void main(String args[]) {
TextInput frame = new TextInput();
frame.pack();
frame.show();
}

static class IntegerDocument extends PlainDocument {

public void insertString(int offset, String string, AttributeSet attributes)
throws BadLocationException {

if (string == null) {
return;
} else {
String newValue;
int length = getLength();
if (length == 0) {
newValue = string;
} else {
String currentContent = getText(0, length);
StringBuffer currentBuffer =
new StringBuffer(currentContent);
currentBuffer.insert(offset, string);
newValue = currentBuffer.toString();
}
try {
Integer.parseInt(newValue);
super.insertString(offset, string, attributes);
} catch (NumberFormatException exception) {
Toolkit.getDefaultToolkit().beep();
}
}
}
}
}

네 개의 텍스트 필드 전부에 대해서 복사해서 붙이기를 해서 어떻게 되나 봐라. 예를 들면, 첫번째 KeyListener 기법을 사용해서 검사하는 텍스트 필드는 숫자가 아닌 것을 붙이기 하면 필드에 입력이 되어버린다. 이런 현상을 처리하려면 붙이기가 안되게 해야될 것이다. 반면에, "Model"이라고 되어 있는 IntegerDocument로 검사하는 텍스트 필드는 제대로 동작을 해서 붙이기가 되지 않는다.
프로그램을 AWT의 TextField로 바꾸려고 한다면, JTextField에서 지원되지 않지만 TextField에는 가능한 한가지는 컨트롤에 TextListener를 붙일 수 있다는 것이다. (역주: TextField의 슈퍼클래스인 java.awt.TextComponent에서 제공하는 메소드이다. javax.swing.text.JTextComponent에는 없다.) 그러나, 사용자 정의 Document를 붙이는 데이터 모델을 사용함으로써 이것을 쉽게 대체할 수 있다. Document는 값이 바뀌었을 때 통보되는 것에 (혹은, 적어도 바꾸고 깊어하는 것에) 직접적으로 연결해 사용한다. (역주:이 마지막 문장은 좀 잘 모르겠더라구요. 고민 끝에 이렇게 해석했는데, 이상하다고 생각되시면, 원문을 한 번 참조해 보세요..^^) [원문보기] If you are transitioning a program with an AWT TextField component to a Swing JTextField, note that one TextField behavior that is not supported on the JTextField is the ability to attach a TextListener to the control. However, you can you can easily replace this behavior by using the data model approach of attaching a custom Document. The Document usage directly maps to being notified when the value of the text has changed (or, at least, wants to change).
스윙 텍스트 컴포넌트에 대해 더 공부하고 싶으면 자바 튜토리얼의 Creating a GUI with JFC/Swing 뒷부분에 스윙 컴포넌트 사용하기 강좌를 참조해라.
반응형

HTML에 자바 스크립트 써보신 분이면 alert("알림메시지"); 기능을 많이 써보셨을 겁니다. VB(비주얼 베이직)에서도 MsgBox 함수로 알림창을 띄울 수 있지요. 자바라고 없겠습니까, 당연히 알림창 기능 있습니다.

그런데 저는 알림창을 띄울 수 있는 클래스가 뭔지 몰라서 한참동안 직접 JDialog로 알림창 비슷한 걸 만들어서 사용했답니다. 왠지 억울한 기분이 들더군요.

※ 자바 스윙(Java Swing, AWT 등)에서 알림창 띄우기
- JOptionPane 1. 종합편

(기타 관련 명칭 : 알림창, 확인창, 대화창, 경고창, 질문창, 메시지창, 메시지박스, MessageBox, MsgBox, Alert창, Confirm Dialog, Message Dialog 등...)

JOptionPane 클래스 하나만 알고 있으면 됩니다. 여기에 윈도우 기본 창들이 많이 들어있습니다.(물론, 파일 열기/닫기에 쓰이는 것은 FileDialog에 있지만요)

이번 강좌 아닌 강좌에 '넷빈즈 IDE(NetBeans IDE)로 하는 자바 프로그래밍'이라는 제목을 달지 않은 이유는, JOptionPane은 IDE 환경에서 사용하든, 메모장 텍스트 박치기로 프로그래밍하든 관계없이 똑같이 한 두 줄로 해결 가능한 것이니까요.

- JOptionPane 클래스 Java API
JOptionPane의 대표적인 정적 메소드 함수(static methods)들로 확인창, 알림창, 질문창 등을 띄울 수 있습니다.

showMessageDialog : 단순 알림창(경고창, 메시지 박스)을 띄웁니다.
showConfirmDialog : 확인창(예/아니오, 확인/취소 등)을 띄웁니다.
showInputDialog : 질문창을 띄웁니다. 간단한 입력 결과를 받습니다.
showOptionDialog : 확인창과 비슷한데, 예/아니오 대신 선택 버튼의 말을 직접 정해줄 수 있습니다.

위에 소개한 세가지 메소드이 자세한 사용법은 각각 따로 글을 작성하겠습니다.
- JOptionPane 2. 알림 메시지 창 띄우기 상세 설정 showMessageDialog
- JOptionPane 3. 확인창 띄우기 상세 설정 showConfirmDialog
- JOptionPane 4. 입력창 띄우기 상세 설정 showInputDialog
- JOptionPane 5. showOptionDialog 마음대로 주무르기

그 외 JOptionPane 클래스에 대한 내용은 JOptionPane Class 자바 API자바 튜토리얼(대화창 띄우는 법)을 참고하시고, 일단 여기서는 간단한 사용법과 예제만 보여드리겠습니다.

우선 JOptionPane 클래스 패키지를 import 해야합니다. 자바 소스 코드 최상단에 다음 import 문을 추가합니다.

import javax.swing.JOptionPane;

본문 중 창을 띄우고 싶은 부분에서 아래 예제를 따라 창을 띄웁니다.

사용자 삽입 이미지

JOptionPane.showMessageDialog(null, "기본 알림창입니다.");

사용자 삽입 이미지

int result = 0;
result = JOptionPane.showConfirmDialog(null, "기본 확인창입니다.");
// (result 리턴값)
// JOptionPane.YES_OPTION, JOptionPane.NO_OPTION,
// JOptionPane.CANCEL_OPTION 등

사용자 삽입 이미지

String resultStr = null;
resultStr = JOptionPane.showInputDialog("기본 입력창입니다.");
// (resultStr 리턴값으로 입력받은 메시지 문자열을 리턴해준다.)

<출처: http://hallang.tistory.com >
반응형

※ 알림 메시지 띄우기 - JOptionPane 2. showMessageDialog
(기타 관련 명칭 : 알림창, 확인창, 대화창, 경고창, 질문창, 메시지창, 메시지박스, MessageBox, MsgBox, Alert창, Confirm Dialog, Message Dialog 등...)

메시지 다이얼로그는 리턴값이 없습니다(void 형). 역시 JOptionPane 클래스 패키지를 import 해야합니다. 자바 소스 코드 최상단에 다음 import 문을 추가합니다.

import javax.swing.JOptionPane;


※ showMessageDialog 메소드 함수 형태

- 리턴 함수 타입 : public static void (되돌려 주는 값이 없습니다)
showMessageDialog( Component parentComponent, Object message )
showMessageDialog( Component parentComponent, Object message,
           String title, int messageType )
showMessageDialog( Component parentComponent, Object message,
           String title, int messageType, Icon icon )



※ 매개변수(파라메터, Parameter) 설명

- Component parentComponent
메시지창 다이얼로그가 어떤 Frame에서 나타나게 될 것인지를 정해주는 변수. null 값이거나 설정해준 값에 Frame이 없다면 기본값 Frame(default Frame)이 지정됩니다. 쉽게 null 로 둬도 될 것 같네요.

- Object message
출력할 Object 클래스형 개체. 주로 문자열 메시지를 출력할 것이므로, 간단하게 그냥 출력할 문자열 자체를 써주면 됩니다. 문자열을 여러줄에 걸쳐서 표현하고 싶다면 newline에 해당하는 escape 문자열(" \n ")을 써주면됩니다.

- String title
메시지창 상단 제목표시줄에 나타낼 알림창 제목입니다.

- int messageType
알림창의 메시지 종류를 정해줍니다. 여기서 정해주는 메시지 종류에 따라 자동으로 지정된 아이콘이 표시됩니다. 자세한 설정 방법은 아래와 같습니다.

JOptionPane.showMessageDialog(null, "기본 알림창입니다.");

사용자 삽입 이미지
아무런 메시지 타입도 지정해주지 않은 경우 디폴트 값입니다.

JOptionPane.showMessageDialog(null, "경고 메시지 내용", "경고 메시지 제목", JOptionPane.WARNING_MESSAGE);
JOptionPane.WARNING_MESSAGE

JOptionPane.WARNING_MESSAGE

JOptionPane.showMessageDialog(null, "오류 메시지 내용", "오류 메시지 제목", JOptionPane.ERROR_MESSAGE);
JOptionPane.ERROR_MESSAGE

JOptionPane.ERROR_MESSAGE

JOptionPane.showMessageDialog(null, "아이콘 없는 메시지 내용", "아이콘 없는 메시지 제목", JOptionPane.PLAIN_MESSAGE);
JOptionPane.PLAIN_MESSAGE

JOptionPane.PLAIN_MESSAGE

JOptionPane.showMessageDialog(null, "정보 메시지 내용", "정보 메시지 제목", JOptionPane.INFORMATION_MESSAGE);
JOptionPane.INFORMATION_MESSAGE

JOptionPane.INFORMATION_MESSAGE

JOptionPane.showMessageDialog(null, "질문 메시지 내용", "질문 메시지 제목", JOptionPane.QUESTION_MESSAGE);
JOptionPane.QUESTION_MESSAGE

JOptionPane.QUESTION_MESSAGE

 

- Icon icon
Icon 클래스를 통해서 직접 정해줄 수도 있습니다. 아이콘 클래스는 제가 잘 모르겠네요 죄송^^ 웬만하면 위 메시지 종류 선택으로 적당히 커버는 될 겁니다. 직접 사용자 아이콘을 정해주려면 Icon 클래스 관련 내용을 공부하셔야 할 거 같네요. null 로 해두면 기본값이 출력되는 것 같습니다.

<출처: http://hallang.tistory.com >

반응형

※ 확인창 메시지 띄우기 - JOptionPane 3. showConfirmDialog

JOptionPane 클래스 패키지를 import 해야합니다. 자바 소스 코드 최상단에 다음 import 문을 추가합니다.

import javax.swing.JOptionPane;


※ showConfirmDialog 메소드 함수 형태

- 리턴값(static int) : 사용자의 확인 버튼 선택값을 되돌려줍니다.
CLOSED_OPTION - 종료(X) 버튼으로 창을 닫은 경우. CANCEL / NO와 비슷하게 처리해줘야합니다.
YES_OPTION - 예(YES) 버튼 선택시 리턴값
NO_OPTION - 아니오(NO) 버튼 선택시
CANCEL_OPTION - 취소(CANCEL) 버튼 선택시
OK_OPTION - 확인(OK) 버튼 선택시

- 메소드 함수 형태 종류
showConfirmDialog( Component parentComponent, Object message )
showConfirmDialog( Component parentComponent, Object message,
         String title, int optionType)
showConfirmDialog( Component parentComponent, Object message,
         String title, int optionType,
         int messageType )
showConfirmDialog( Component parentComponent, Object message,
         String title, int optionType,
         int messageType, Icon icon )



※ 매개변수(파라메터, Parameter) 설명

- Component parentComponent
메시지창 다이얼로그가 어떤 Frame에서 나타나게 될 것인지를 정해주는 변수. null 값이거나 설정해준 값에 Frame이 없다면 기본값 Frame(default Frame)이 지정됩니다. 쉽게 null 로 둬도 될 것 같네요.

- Object message
출력할 Object 클래스형 개체. 주로 문자열 메시지를 출력할 것이므로, 간단하게 그냥 출력할 문자열 자체를 써주면 됩니다. 문자열을 여러줄에 걸쳐서 표현하고 싶다면 newline에 해당하는 escape 문자열(" \n ")을 써주면됩니다.

- String title
메시지창 상단 제목표시줄에 나타낼 알림창 제목입니다.

- int optionType
사용자의 대답 선택 버튼을 어떻게 표현할 것인가 결정합니다. "예", "아니오", "취소" 버튼을 어떤 식으로 배치할 지 결정합니다.
YES_NO_OPTION
YES_NO_CANCEL_OPTION
OK_CANCEL_OPTION
위 버튼의 텍스트(예, 아니오)를 다른 글자로 바꿀 수 있습니다. showOptionDialog를 통해서 간으한 작업으로, 자세한 건 showOptionDialog 설명글을 참고하세요!

- int messageType
알림창의 메시지 종류를 정해줍니다. 여기서 정해주는 메시지 종류에 따라 자동으로 지정된 아이콘이 표시됩니다.
ERROR_MESSAGE
INFORMATION_MESSAGE
WARNING_MESSAGE
QUESTION_MESSAGE

아이콘 없음 :
PLAIN_MESSAGE

- Icon icon
Icon 클래스를 통해서 직접 정해줄 수도 있습니다. 아이콘 클래스는 제가 잘 모르겠네요 죄송^^ 웬만하면 위 메시지 종류 선택으로 적당히 커버는 될 겁니다. 직접 사용자 아이콘을 정해주려면 Icon 클래스 관련 내용을 공부하셔야 할 거 같네요. null 로 해두면 기본값이 출력되는 것 같습니다.


※ 사용 예제
JOptionPane.showConfirmDialog(null, "기본 확인창입니다.");

사용자 삽입 이미지
아무런 타입도 지정해주지 않은 경우 디폴트 값

JOptionPane.showConfirmDialog(null, "경고 메시지 + 예/아니오 옵션", "제목표시줄", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
example

JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE

 <출처: http://hallang.tistory.com >

+ Recent posts