잘사용하시면, 간편하게 훌륭한 대화상자들을 만들어 낼수 있습니다.

끝부분에 커스터마이징 부분을 잘 보시길 바랍니다.

 

BEYOND THE BASICS OF JOPTIONPANE

The Swing component set in J2SE includes a special class for creating a panel to be placed in a popup window. You can use this panel to display a message to the user and to get a response from the user. The panel presents content in four areas, one each for an icon, message, input, and buttons. You don't need to use any of the areas, although you would typically present at least a message and a button.

The icon area is for the display of a javax.swing.Icon. The icon is meant to indicate the type of message being displayed. There are default icons provided by the specific look and feel you use. The default images for these icons are specified through a property setting to the look and feel. The property setting points to the appropriate resource for each message type:

  • OptionPane.informationIcon
  • OptionPane.warningIcon
  • OptionPane.errorIcon
  • OptionPane.questionIcon

You don't have to change the default properties, though you could with a call to UIManager.put(property name, new resource). With the defaults in place, you simply identify the appropriate message type with a constant of JOptionPane:

  • JOptionPane.PLAIN_MESSAGE
  • JOptionPane.INFORMATION_MESSAGE
  • JOptionPane.WARNING_MESSAGE
  • JOptionPane.ERROR_MESSAGE
  • JOptionPane.QUESTION_MESSAGE

The plain variety maps to no icon, while the others use a default icon from the look and feel.

The second area of the JOptionPane is the message area. This is typically used to display a text message. However, you could show any number of objects here. The message type determines how a message is displayed.

The input area is next. Here is where you can get a response to a message from the user. To prompt for a response you can use a free form text field, a combo box, or even a list control. For Yes/No type prompts, you would instead use the button area, described next.

Last is the button area, another response-like area. When a user selects a button it signals the end of usage for the JOptionPane. Default sets of button labels are available. (As is the case for icons, these too come from property settings, such as OptionPane.yesButtonText.) You can also provide your own button labels. You can display any number of buttons (including no buttons) with any set of labels. The predefined button label is localized for several languages: English (en), German (de), Spanish (es), French (fr), Italian (it), Japanese (ja), Korean (ko), Swedish (sv), and two varieties of Chinese (zh_CN / zh_TW). If you provide your own labels, you need to localize them yourself.

The predefined sets of buttons are defined by a set of JOptionPane constants:

  • DEFAULT_OPTION
  • YES_NO_OPTION
  • YES_NO_CANCEL_OPTION
  • OK_CANCEL_OPTION

Default maps to a single OK button.

Using JOptionPane

The JOptionPane class contains seven constructors, each returns a component that you can place anywhere. However, more typically you would use a factory method that creates the component and automatically places it inside a JDialog or JInternalFrame. There are eight of these factory methods (two varieties of four methods) that JOptionPane provides:

  • show[Internal]MessageDialog
  • show[Internal]ConfirmDialog
  • show[Internal]InputDialog
  • show[Internal]OptionDialog

The Internal variety creates a JOptionPane and shows it in a JInternalFrame. The other variety creates a JOptionPane and shows it in a JDialog. This tip only discusses the dialog variety.

The message dialog is meant to show a message that the user confirms by selecting the button (or closing the dialog). The message dialog is not meant to return a value.

In its simplest case, you would use code like the following to show a message dialog:

   JOptionPane.showMessageDialog(
      component, "Hello, World");

The system centers the dialog over the component argument.

There are two other variations for showing a message dialog. These allow you to customize the window title, customize the message type (to use the default icon), and set a customized icon:

  • showMessageDialog(Component parentComponent,
    Object message,
    String title,
    int messageType)
  • showMessageDialog(Component parentComponent,
    Object message,
    String title,
    int messageType,
    Icon icon)

The method for showing a confirm dialog has four variations:

  • 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)

The simplest variation brings up a dialog with a question icon. The dialog displays Select an Option as the title, has Yes, No, and Cancel as button labels.

   JOptionPane.showConfirmDialog(component, "Lunch?");

If you don't like the defaults, you can change them by using one of the other methods. You'll find that everything is changeable with JOptionPane.

Unlike the message dialog, the confirm dialog does require a return value. Here, you really do want to know which button the user selected. The confirm dialog returns an integer, indicated by one of the following constants of the JOptionPane class:

  • CANCEL_OPTION
  • CLOSED_OPTION (used when the used closed popup window)
  • NO_OPTION
  • OK_OPTION
  • YES_OPTION

Passing in a setting of OK_CANCEL_OPTION for the option type changes the buttons shown in the confirm dialog to OK and Cancel. Comparing the value returned to the constant, indicates which button the user selected.

Checking for the return value changes the one line above to quite a few more:

   int returnValue = JOptionPane.showConfirmDialog(
     component, "Lunch?");
   String message = null;
   if (returnValue == JOptionPane.YES_OPTION) {
     message = "Yes";
   } else if (returnValue == JOptionPane.NO_OPTION) {
     message = "No";
   } else if (returnValue == JOptionPane.CANCEL_OPTION) {
     message = "Cancel";
   } else if (returnValue == JOptionPane.CLOSED_OPTION) {
     message = "Closed";
   }
   System.out.println("User selected: " + message);

The input dialog method has six variations. Five return a String:

  • showInputDialog(Object message)
  • showInputDialog(Object message,
    Object initialSelectionValue)
  • showInputDialog(Component parentComponent,
    Object message)
  • showInputDialog(Component parentComponent,
    Object message,
    Object initialSelectionValue)
  • showInputDialog(Component parentComponent,
    Object message,
    String title,
    int messageType)

One of the variations returns an Object:

  • showInputDialog(Component parentComponent,
    Object message,
    String title,
    int messageType,
    Icon icon,
    Object[] selectionValues,
    Object initialSelectionValue)

The simplest variation shows the message in a question dialog. The dialog displays Input as the frame title, and has OK and Cancel buttons. Because there is no component provided, the frame is centered over the whole screen.

   String value = JOptionPane.showInputDialog("Name");

As is the case for other types, when you show the input dialog, you can set the parent component, frame title, message type, or icon. However the buttons are fixed at OK and Cancel. You can also set the initial value in the text field.

The last method variation for the input dialog is special. Instead of offering the user a text field to enter selections, you provide an array of objects (typically strings) from which to choose. Depending on how many values you provide, the look and feel will present either a JComboBox or JList for the user selections. Here's an example that uses this variation. Here an input dialog prompts a user to select a day of the week. The default is the last day of the week. The example uses a smallList for the days of the week.

   String smallList[] = {
     "Sunday",
     "Monday",
     "Tuesday",
     "Wednesday",
     "Thursday",
     "Friday",
     "Saturday"
   };
   String value = 
     (String)JOptionPane.showInputDialog(
       component, 
       "Which Day?", 
       "Day", 
       JOptionPane.QUESTION_MESSAGE, 
       null, // Use default icon
       smallList, 
       smallList[smallList.length-1]);
   System.out.println("Day: " + value);

For a larger list, the code looks essentially the same. Here the list of system properties are used as the choices.

   Object largeList[] = 
     System.getProperties().keySet().toArray();
   String value = 
     (String)JOptionPane.showInputDialog(
       component, 
       "Which Property?", 
       "Property", 
      JOptionPane.QUESTION_MESSAGE, 
       null, 
       largeList, 
       largeList[largeList.length-1]);


   System.out.println("Property: " + value);

The final dialog type is an all encompassing one, showOptionDialog. There is only one version of the method. Here, you can set everything:

  • showOptionDialog(Component parentComponent,
    Object message,
    String title,
    int optionType,
    int messageType,
    Icon icon,
    Object[] options,
    Object initialValue)

The only thing new here is the options array. This is how you can customize the set of available buttons. Notice that this is an Object array, not a String array. If the Object is a Component, that component is used in the dialog. This allows you to place icons in the buttons, for instance. More typically, you would provide an array of strings, and their labels would be used as the button labels. The initialValue is then used to select which of the options gets the default selection.

The showOptionDialog method returns an int. This indicates the position selected from the options array. CLOSED_OPTION is still returned if the user closed the dialog.

   String options[] = {"Yes", "Not Now", "Go Away"};
   int value = JOptionPane.showOptionDialog(
       component,
       "Lunch?",
       "Lunch Time",
       JOptionPane.YES_NO_OPTION, // Need something  
         JOptionPane.QUESTION_MESSAGE,
       null, // Use default icon for message type
       options,
       options[1]);
   if (value == JOptionPane.CLOSED_OPTION) {
     System.out.println("Closed window");
   } else {
     System.out.println("Selected: " + options[value]);
   }

If you don't want buttons, pass in an empty array for the options.

Adding Word Wrap

The JOptionPane component has a read-only property (MaxCharactersPerLineCount) for the maximum number of characters per line. By default, this is Integer.MAX_VALUE. By subclassing JOptionPane, you can override this setting. Changing this setting allows the component to word-wrap when a message is really long.

   public static JOptionPane getNarrowOptionPane(
                       int maxCharactersPerLineCount) {
     // Our inner class definition
     class NarrowOptionPane extends JOptionPane {
       int maxCharactersPerLineCount;
       NarrowOptionPane(int maxCharactersPerLineCount) {
         this.maxCharactersPerLineCount = 
           maxCharactersPerLineCount;
       }
       public int getMaxCharactersPerLineCount() {
         return maxCharactersPerLineCount;
       }
     }


     return new NarrowOptionPane(
       maxCharactersPerLineCount);
   }

By subclassing, you can no longer use the static helper methods such as showMessageDialog. Here's how you manually create and show the component:

   String msg = "This is a really long message. ...";
   JOptionPane pane = getNarrowOptionPane(50);
   pane.setMessage(msg);
   pane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
   JDialog dialog = pane.createDialog(
     component, "Width 50");
   dialog.show();

Of course, you can add a "\n" to the message, but then you have to count the characters per line.

Message as Object

At this point you might ask why the message argument to all the showXXXDialog methods is an Object. The answer is that it's because the message argument to all these methods doesn't have to be a String. You can pass in any Object. Each object is "added" to the message area, one on top of the other. For instance, if you pass in an array of two strings, it creates a message on two lines:

   String msg[] = {"Welcome", "Home"};
   JOptionPane.showMessageDialog(component, msg);

The objects you add can be components, icons, or objects. Components are added as such. Icons are shown in a label, as are strings. For other objects, their string representation (toString()) is shown. For instance, the following component can be added to an option pane. As the user changes the selection in the slider, the option pane's value is updated:

   public static JSlider getSlider(
                        final JOptionPane optionPane) {
     JSlider slider = new JSlider();
     slider.setMajorTickSpacing (10);
     slider.setPaintTicks(true);
     slider.setPaintLabels(true);
     ChangeListener changeListener = 
       new ChangeListener() {
       public void stateChanged(
                   ChangeEvent changeEvent) {
         JSlider theSlider = 
             (JSlider)changeEvent.getSource();
         if (!theSlider.getValueIsAdjusting()) {
           optionPane.setInputValue(
             new Integer(theSlider.getValue()));
         }
       }
     };
     slider.addChangeListener(changeListener);
     return slider;
   }

Because you have to pass the option pane to the method, here again, you can't use one of the shortcuts to create the dialog:

   JOptionPane optionPane = new JOptionPane();
   JSlider slider = getSlider(optionPane);
   Object msg[] = {"Select a value:", slider};
   optionPane.setMessage(msg);
   optionPane.setMessageType(
     JOptionPane.QUESTION_MESSAGE);
   optionPane.setOptionType(
     JOptionPane.OK_CANCEL_OPTION);
   JDialog dialog = optionPane.createDialog(
       Options.this, "Select Value");
   dialog.show();
   Object value = optionPane.getValue();
   if (value == null || !(value instanceof Integer)) {
     System.out.println("Closed");
   } else {
     int i = ((Integer)value).intValue();
     if (i == JOptionPane.CLOSED_OPTION) {
       System.out.println("Closed");
     } else if (i == JOptionPane.OK_OPTION) {
       System.out.println("OKAY - value is: " +
                  optionPane.getInputValue());
     } else if (i == JOptionPane.CANCEL_OPTION) {
       System.out.println("Cancelled");
     }
   }

Notice that as you start getting fancier with JOptionPane, you lose the ability to use the shortcut methods. And, you have to do special handling of the return value. You first need to use getValue for the JOptionPane to determine which button the user selected. Then, for when the user presses the OK button, you need to use the getInputValue method to get the value from the underlying slider.

Sounds

Swing provides for auditory cues related to the four types of icons:

  • OptionPane.errorSound
  • OptionPane.informationSound
  • OptionPane.questionSound
  • OptionPane.warningSound

By setting these properties, you can get sounds when your option panes are displayed. You can set the individual sounds with lines like the following:

   UIManager.put("OptionPane.questionSound", 
     "sounds/OptionPaneError.wav");

Or set all of them with the system defaults as follows:

   UIManager.put("AuditoryCues.playList",
     UIManager.get("AuditoryCues.defaultCueList"));

Audio cues are disabled by default because they might have problems on some platforms. It is recommended that you use them with care until the issues have been resolved.

Complete Example

Here is the source code for a complete example that uses the features explored in this tip.

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

   public class Options extends JFrame {
     private static class FrameShower
         implements Runnable {
       final Frame frame;
       public FrameShower(Frame frame) {
         this.frame = frame;
       }
       public void run() {
         frame.show();
       }
     }

     public static JOptionPane getNarrowOptionPane(
         int maxCharactersPerLineCount) {
       // Our inner class definition
       class NarrowOptionPane extends JOptionPane {
         int maxCharactersPerLineCount;
         NarrowOptionPane(
                   int maxCharactersPerLineCount) {
           this.maxCharactersPerLineCount = 
              maxCharactersPerLineCount;
     }
         public int getMaxCharactersPerLineCount() {
           return maxCharactersPerLineCount;
         }
       }

    return new NarrowOptionPane(
               maxCharactersPerLineCount);
  }

     public static JSlider getSlider(
                        final JOptionPane optionPane) {
       JSlider slider = new JSlider();
       slider.setMajorTickSpacing (10);
       slider.setPaintTicks(true);
       slider.setPaintLabels(true);
       ChangeListener changeListener = 
                            new ChangeListener() {
         public void stateChanged(
                           ChangeEvent changeEvent) {
           JSlider theSlider = (
             JSlider)changeEvent.getSource();
           if (!theSlider.getValueIsAdjusting()) {
             optionPane.setInputValue(new Integer(  
               theSlider.getValue()));
           }
         }
       };
       slider.addChangeListener(changeListener);
       return slider;
     }

     public Options() {
       super("JOptionPane Usage");
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       Container contentPane = getContentPane();
       contentPane.setLayout(new FlowLayout());
       JButton message = new JButton("Message");
       ActionListener messageListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           JOptionPane.showMessageDialog(
             Options.this, "Hello, World");
         }
       };
       message.addActionListener(messageListener);
       contentPane.add(message);
       JButton confirm = new JButton("Confirm");  
       ActionListener confirmListener = 
        new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           int returnValue = 
             JOptionPane.showConfirmDialog(
           Options.this, "Lunch?");
           String message = null;           
           if (returnValue == JOptionPane.YES_OPTION) {
             message = "Yes";
           } else if (
               returnValue == JOptionPane.NO_OPTION) {
             message = "No";
           } else if (
               returnValue == JOptionPane.CANCEL_OPTION) {
             message = "Cancel";
           } else if (
               returnValue == JOptionPane.CLOSED_OPTION) {
             message = "Closed";
           }
           System.out.println("User selected: " + message);
         }
       };
       confirm.addActionListener(confirmListener);
       contentPane.add(confirm);
       JButton inputText = new JButton("Input Text");
       ActionListener inputTextListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String value = 
             JOptionPane.showInputDialog("Name");
           System.out.println("Name: " + value);
         }
       };
       inputText.addActionListener(inputTextListener);
       contentPane.add(inputText);
       JButton inputCombo = new JButton("Input Combo");
       ActionListener inputComboListener = 
                                 new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String smallList[] = {
             "Sunday",
             "Monday",
             "Tuesday",
             "Wednesday",
             "Thursday",
             "Friday",
             "Saturday"
           };
           String value = 
             (String)JOptionPane.showInputDialog(
             Options.this, "Which Day?", "Day", 
             JOptionPane.QUESTION_MESSAGE, null, 
             smallList, smallList[smallList.length-1]);
           System.out.println("Day: " + value);
         }
       };
       inputCombo.addActionListener(inputComboListener);
       contentPane.add(inputCombo);
       JButton inputList = new JButton("Input List");     
       ActionListener inputListListener = 
                              new ActionListener() {
        public void actionPerformed(ActionEvent e) {
           Object largeList[] = 
             System.getProperties().keySet().toArray();
           String value = 
             (String)JOptionPane.showInputDialog(
             Options.this, "Which Property?", "Property", 
             JOptionPane.QUESTION_MESSAGE, null, 
             largeList, largeList[largeList.length-1]);
             System.out.println("Property: " + value);
         }
       };              
       inputList.addActionListener(inputListListener);
       contentPane.add(inputList);
       JButton all = new JButton("All");
       ActionListener allListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String options[] = 
             {"Yes", "Not Now", "Go Away"};
           int value = JOptionPane.showOptionDialog(
               Options.this,
               "Lunch?",
               "Lunch Time",
               JOptionPane.YES_NO_OPTION, 
               // Message type
               JOptionPane.QUESTION_MESSAGE,
               null, // Use default icon for message type
               options,
               options[1]);
           if (value == JOptionPane.CLOSED_OPTION) {
             System.out.println("Closed window");
           } else {
             System.out.println(
               "Selected: " + options[value]);
           }
         }
       };       
       all.addActionListener(allListener);
       contentPane.add(all);
       JButton wide = new JButton("Wide");
       ActionListener wideListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String msg = 
             "This is a really long message. " + 
             "This is a really long message. " + 
             "This is a really long message. " + 
             "This is a really long message. " + 
             "This is a really long message. " +
             "This is a really long message.";
           JOptionPane pane = getNarrowOptionPane(50);
           pane.setMessage(msg);
           pane.setMessageType(
             JOptionPane.INFORMATION_MESSAGE);
           JDialog dialog = 
              pane.createDialog(Options.this, "Width 50");
           dialog.show();
         }
       };       
       wide.addActionListener(wideListener);
       contentPane.add(wide);
       JButton twoLine = new JButton("Two Line");
       ActionListener twoLineListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String msg[] = {"Welcome", "Home"};
           JOptionPane.showMessageDialog(
             Options.this, msg);
         }
       };       
       twoLine.addActionListener(twoLineListener);
       contentPane.add(twoLine);
       JButton slider = new JButton("Slider");
       ActionListener sliderListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           JOptionPane optionPane = new JOptionPane();
           JSlider slider = getSlider(optionPane);
           Object msg[] = {"Select a value:", slider};
           optionPane.setMessage(msg);
           optionPane.setMessageType(
             JOptionPane.QUESTION_MESSAGE);
           optionPane.setOptionType(
             JOptionPane.OK_CANCEL_OPTION);
             JDialog dialog = optionPane.createDialog(
                Options.this, "Select Value");
           dialog.show();
           Object value = optionPane.getValue();
           if (value == null || !(value instanceof Integer)) {
             System.out.println("Closed");
           } else {
             int i = ((Integer)value).intValue();
             if (i == JOptionPane.CLOSED_OPTION) {
               System.out.println("Closed");
             } else if (i == JOptionPane.OK_OPTION) {
               System.out.println("OKAY - value is: " +
                          optionPane.getInputValue());
             } else if (i == JOptionPane.CANCEL_OPTION) {
               System.out.println("Cancelled");
             }
           }
         }
       };
       slider.addActionListener(sliderListener);
       contentPane.add(slider);
       setSize(300, 200);
     }
     
     public static void main(String args[]) {
       UIManager.put("AuditoryCues.playList",
         UIManager.get("AuditoryCues.defaultCueList"));
       JFrame frame = new Options();
       Runnable runner = new FrameShower(frame);
       EventQueue.invokeLater(runner);
     }
   }

For additional information about JOptionPane, see the How to Make Dialogs trail in The Java Tutorial and the javadoc for the JOptionPane class.


'자바 > 자바팁' 카테고리의 다른 글

클래스패스 설정  (0) 2010.10.25
Borderlayout 기본설명  (0) 2010.10.21
에코 클라이언트 과정  (0) 2010.10.21
JFrame 관련 팁  (0) 2010.10.18
action event 를 쓸때 컴파일시 inner class 에러 나는 경우  (0) 2010.10.18

+ Recent posts