다이얼로그 Modality

Java SE 2006/06/09 09:31 Posted by Sun
'Java-speak'의 최상위(top-level) 팝업 윈도우를 다이얼로그 박스(또는 간단히 '다이얼로그')라고 하는데, 이는 메시지를 표시하거나 사용자의 입력을 받기 위한 사용자와의 인터랙트에 주로 사용된다. Java SE 6 이전에는 다이얼로그 박스의 기본값이 modeless로, 옵션은 modal로 지정되어 있었다. 다이얼로그 박스가 modal인 경우에는 애플리케이션의 다른 윈도우는 (다이얼로그 박스가 윈도우의 해당 소유자가 아닌 이상) 입력이 차단된다. 사용자가 입력을 하거나 다이얼로그를 그냥 닫는 등 다이얼로그 박스에 반응한 후에는 애플리케이션의 다른 윈도우가 다시 활성화된다.

Java SE 6는 다이얼로그 modality에 관한 더 많은 옵션을 제공하며, 이제는 더 이상 한 가지 레벨의 modality(on 또는 off)로만 범위가 제한되지 않는다. 또한 새로운 Dialog.ModalityType enumeration에 의해 정의되는 4가지의 별도의 설정을 사용할 수 있게 되었다.
  • MODELESS
  • APPLICATION_MODAL
  • DOCUMENT_MODAL
  • TOOLKIT_MODAL
먼저 MODELESSAPPLICATION_MODAL을 살펴보도록 하자. MODELESS 설정은 modeless 다이얼로그 박스를 의미하는데, 이전과 마찬가지로 modeless 다이얼로그 박스는 애플리케이션의 어떠한 다른 윈도우에 대한 입력도 차단하지 않는다. 즉, 다른 modal 다이얼로그 박스는 입력을 차단할 수 있지만 modeless 다이얼로그 박스는 전혀 영향을 주지 않는다. false 값으로 Dialog 클래스의 setModal() 메소드를 호출할 경우에는 Dialog.ModalityTypeMODELESS로 설정된다.

APPLICATION_MODAL 설정은 modal 다이얼로그 박스를 의미하며, 이전과 마찬가지로 소유자 계층에 modal 다이얼로그 박스를 가지지 않는 모든 애플리케이션의 윈도우는 포커스를 얻지 못하게 된다. 이는 modal 다이얼로그에서 새 윈도우가 생성되어 입력을 받을 수 있음을 의미하는 반면, 기존의 다른 윈도우에서 만들어진 새 윈도우는 그렇지가 못하다. true 값으로 DialogsetModal() 메소드를 호출할 경우에는 Dialog의 modality가 APPLICATION_MODAL과 일치하는 DEFAULT_MODALITY_TYPE으로 설정된다. 이로써 레거시 코드의 유효성이 유지되지만, 새 코드는 새로운 setModalityType() 메소드를 사용해야 한다.

이 시점에서 독자들은 modality를 명확하게 지정하지 않으면 어떻게 될까 하는 궁금증이 생길 것이다. 그 대답은 초기 modality가 modeless로 되어 있다는 것이고, 또한 불(boolean) modality를 지정하면 해당 불 값으로 setModal()을 호출하는 것과 동일한 설정이 생성된다는 것이다. 마지막 옵션은 뚜렷한 효과를 가지는 modality를 정확하게 설정할 수 있다.

DOCUMENT_MODALTOOLKIT_MODAL은 흥미로운 특성을 지니고 있다. DOCUMENT_MODAL은 modal인 윈도우의 다양한 세트를 가질 수 있게 해주는데, 예를 들어 헬프 윈도우를 표시하는 modal 애플리케이션 윈도우를 가질 수 있는 경우가 바로 그것이다. 메인 애플리케이션의 계층에 속하지 않는 최상위(top-level) 윈도우를 가질 경우에는 헬프 윈도우가 modal이 될 수 있으며, 또한 헬프 윈도우는 메인 윈도우와 구분되는, 그리고 헬프 윈도우가 생성하는 그 어떠한 modal 다이얼로그와도 구분되는 별도의 modality를 가지는 다른 modal 윈도우를 만들 수 있다. modal 헬프 윈도우를 표시하는 modal 애플리케이션을 사용하는 것은 JavaHelp 라이브러리 이용 시 공통으로 적용되는 필요사항이다. 한편, 현재의 윈도우가 modal인 경우에라도 사용자가 헬프와 인터랙트할 수 있기를 원하는 경우가 종종 있다. 메인 애플리케이션 윈도우와 헬프 윈도우는 서로 다른 소유자 계층을 가지기 때문에 DOCUMENT_MODAL이 지원되기 전까지는 이런 필요성이 충분히 충족되지 않았던 것이 사실이다.

TOOLKIT_MODALAPPLICATION_MODAL로 생각해보자. 여기서 애플리케이션은 브라우저이다. (본 단락에서 언급되는 애플릿에 관한 얘기는 Java WebStart 기술을 통해 작성된 애플리케이션에도 적용된다.) 이 설정의 경우 브라우저 내의 특정 애플릿이 modal로 되어 다른 애플릿의 입력 허용을 차단할 수 있게 해주는데, 그 이유는 모든 애플릿이 동일한 Toolkit에서 로드되기 때문이다. TOOLKIT_MODAL이 작동하려면 반드시 사용자의 애플릿에 의해 AWTPermission.toolkitModality가 활성화되어야 한다.

사용자는 윈도우의 modality 타입을 설정하는 것 외에도 WindowsetModalExclusionType() 메소드를 호출하여 modal exclusion 타입을 설정할 수 있다. 이렇게 하면 특정 윈도우가 관련 modality 타입에 따라 작동하는 것을 차단할 수 있다. setModalExclusionType() 메소드는 Dialog.ModalExclusionType enumeration에서 다음 세 가지 값 중 하나를 수락한다.

  • NO_EXCLUDE
  • APPLICATION_EXCLUDE
  • TOOLKIT_EXCLUDE
NO_EXCLUDE 옵션은 modal exclusion이 없음을 의미하며, 윈도우는 현재의 modality 타입에 따라 동작하게 된다. 다른 두 설정은 modality 타입을 사용할 수 있도록 하는 동시에 특정 윈도우가 입력 포커스를 수락할 수 있게 해준다. APPLICATION_EXCLUDE 설정은 애플리케이션 레벨에서 윈도우가 modality에 따라 동작하지 않을 것임을 명시하고, TOOLKIT_EXCLUDE는 애플리케이션과 Toolkit 레벨 모두에서 윈도우가 modality에 따라 동작하지 않을 것임을 명시한다. 윈도우가 애플리케이션 레벨에서가 아닌 Toolkit 레벨에서 동작을 차단하도록 할 방법은 현재로서는 없다.

modality 타입이나 exclusion 옵션을 이용하기 전에 Toolkit에 대해 해당 옵션의 지원 여부를 물을 수 있다. 특정 modality가 지원되는지 알아보려면 불(boolean) isModalityTypeSupported(Dialog.ModalityType modalityType) 메소드를 이용하고, exclusion 타입의 지원 여부를 알아보려면 불(boolean) isModalExclusionTypeSupported(Dialog.ModalExclusionType modalExclusionType) 메소드를 이용하면 된다.

다음은 DOCUMENT_MODAL 설정이 사용되는 두 가지 프레임을 디스플레이하는 프로그램인 DualModal이다. 각 프레임에는 입력을 수락하는 문서 modal 옵션 페인을 만드는 버튼이 있는데, 선택한 버튼의 라벨은 옵션 페인이 닫힐 때 입력되었던 텍스트로 변하게 된다.

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

   public class DualModal {
     public static void main(String args[]) {
       Runnable runner = new Runnable() {
         public void run() {
           JFrame frame1 = new JFrame("Left");
           JFrame frame2 = new JFrame("Right");
           frame1.setDefaultCloseOperation(
              JFrame.EXIT_ON_CLOSE);
           frame2.setDefaultCloseOperation(
              JFrame.EXIT_ON_CLOSE);
           JButton button1 = new JButton("Left");
           JButton button2 = new JButton("Right");
           frame1.add(button1, BorderLayout.CENTER);
           frame2.add(button2, BorderLayout.CENTER);
           ActionListener listener = new ActionListener() {
             public void actionPerformed(ActionEvent e) {
               JButton source = (JButton)e.getSource();
               String text = getNewText(source);
               if (!JOptionPane.UNINITIALIZED_VALUE.equals(text) 
                  && text.trim().length() > 0) {
                 source.setText(text);
               }
             }
           };
           button1.addActionListener(listener);
           button2.addActionListener(listener);
           frame1.setBounds(100, 100, 200, 200);
           frame1.setVisible(true);
           frame2.setBounds(400, 100, 200, 200);
           frame2.setVisible(true);
         }
       };
       EventQueue.invokeLater(runner);
     }
        private static String getNewText(Component parent) {
          JOptionPane pane = new JOptionPane(
            "New label", JOptionPane.QUESTION_MESSAGE
         );
        pane.setWantsInput(true);
        JDialog dialog = pane.createDialog(parent, "Enter Text");
        // Uncomment line and comment out next 
        //  to see application modal
        // dialog.setModalityType(
        //   Dialog.ModalityType.APPLICATION_MODAL);
        dialog.setModalityType(
           Dialog.ModalityType.DOCUMENT_MODAL);
        dialog.setVisible(true);
        return (String)pane.getInputValue();
     }
   }
최상위 다이얼로그가 표시될 때 어떻게 하면 (다이얼로그의 하위 프레임이 아닌) 최상위 다이얼로그와 인터랙트할 수 있는지 유의할 것.

다음은 초기 프레임 쌍의 형태이다.

dialogmod1 Window

다음은 각각의 옵션 페인을 가지는 두 개의 프레임이다.

dialogmod2 Window

이 때, 독자들은 APPLICATION_MODAL을 이용하기 위해 setModalityType() 행을 변경하면 두 가지 옵션 프레임 모두와 동시에 인터랙트할 수 있으리라는 생각이 들지도 모른다. 하지만 실제로는 그렇지 않다. 한 옵션 프레임의 사용이 완료되어야만 또 다른 옵션 프레임을 불러올 수 있다.

여기서 두 가지 사실을 언급할 필요가 있는데, 이미 표시된 윈도우의 modality를 변경해도 아무런 영향이 없다는 것이며, 또 하나는 새로운 modality 설정이 효력을 발휘하려면 반드시 다이얼로그 박스를 숨겼다가 다시 보이게 해야 한다는 점이다.

아울러, Java SE 6 이전에는 어떠한 AWT 윈도우나 서브클래스도 WindowsetAlwaysOnTop() 메소드를 이용하여 항상 맨위에 표시되도록 요청할 수 있었지만, 이는 modal의 경우와는 달리 다른 윈도우가 입력 포커스를 얻는 것을 막지는 못한다.

다이얼로그 modality에 관한 자세한 내용은 아티클 "Mustang의 새로운 Modality API"를 참조할 것.

"Java SE" 카테고리의 다른 글

2006/06/09 09:31 2006/06/09 09:31

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/160

댓글을 달아 주세요

  1. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 04:24
[로그인][오픈아이디란?]

◀ Prev 1  ... 385 386 387 388 389 390 391 392 393  ... 626  Next ▶