2012-10-24 2 views
8

누군가가 말해 줄 수주십시오 충족 될 때까지 닫지 방지?위한 JOptionPane - 사용자의 입력을 확인하고 조건이 사용자 입력 필드에 대한 조건이 충족되지 않으면 확인을 클릭시 폐쇄에서 방지 <code>JOptionPane</code>하는 편리한 방법이 있는지

또는 내가 JFrame를 사용하는 선택의 여지가 있지만 무엇입니까?

지금까지 나의 검증 논리. 버튼이 몇 가지 이유를 한 번 클릭 할 수 있기 때문에 ... 작동하지 않는 것

final JDialog dialog3 = new JDialog(OmniGUI.getFrame(), "Create new Node - id:" + newNodeID); 
dialog3.setContentPane(theOPane); 
dialog3.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); 

theOPane.addPropertyChangeListener(new PropertyChangeListener(){ 
    public void propertyChange(PropertyChangeEvent e) { 

     if(e.getSource() == theOPane){ 
      String val = (String) ((JOptionPane) e.getSource()).getValue(); 

      if(val=="Create"){ 
       System.out.println("Checking content");      

       if(!valid){ 
        System.out.println("closing the window");  

        dialog3.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
        dialog3.removeAll(); 
        dialog3.dispatchEvent(new WindowEvent(dialog3, WindowEvent.WINDOW_CLOSING)); 
       } 

      } 
     } 
    }  
}); 

    dialog3.setLocation(p); 
    dialog3.pack(); 
    dialog3.setVisible(true); 
+0

? showConfirmDialog, showInputDialog? –

+0

JDialog의 createDialog 또는 setContentPane을 사용하고 있지만 작동한다면 아무 것도 할 수 있습니다. – bioMind

답변

20

당신은 닫거나 이동하기 전에 사용자 입력 등을 확인하기 위해 자신의 사용자 정의 JDialog을 만들 수 있습니다. 이 링크를 참조하십시오 : 기본적으로

Stopping Automatic Dialog Closing

, 사용자가 JOptionPane의 생성 버튼을 클릭하면 대화 상자가 닫히고합니다. 그러나 대화 상자를 닫기 전에 사용자의 응답을 확인하려면 어떻게해야합니까? 이 경우 사용자가 단추를 클릭 할 때 대화 상자가 자동으로 닫히지 않도록 자신의 속성 변경 리스너를 구현해야합니다.

enter image description here

을 당신에게 X을 클릭하면 :

것은 당신이 확인 메시지가 표시됩니다 입력/더 텍스트 잘못 입력하지 않고 클릭하면 다음과 같습니다

은 내가 만든 예입니다 대화 상자를 닫습니다 또는 유효성 검사 메시지를 취소를 클릭도 표시됩니다

enter image description here

올바른 텍스트 (이 경우 "다윗"에서) 입력 및 표시되는 메시지를 클릭 입력하고 JDialog가 종료 된 경우 :

enter image description here

CustomDialog.java :

import java.awt.*; 
import java.awt.event.*; 
import java.beans.*; 
import javax.swing.JDialog; 
import javax.swing.JOptionPane; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

class CustomDialog extends JDialog 
     implements ActionListener, 
     PropertyChangeListener { 

    private String typedText = null; 
    private JTextField textField; 
    private String magicWord; 
    private JOptionPane optionPane; 
    private String btnString1 = "Enter"; 
    private String btnString2 = "Cancel"; 

    /** 
    * Returns null if the typed string was invalid; otherwise, returns the 
    * string as the user entered it. 
    */ 
    public String getValidatedText() { 
     return typedText; 
    } 

    /** 
    * Creates the reusable dialog. 
    */ 
    public CustomDialog(Frame aFrame, String aWord) { 
     super(aFrame, true); 

     magicWord = aWord.toUpperCase(); 
     setTitle("Quiz"); 

     textField = new JTextField(10); 

     //Create an array of the text and components to be displayed. 
     String msgString1 = "What was Dr. SEUSS's real last name?"; 
     String msgString2 = "(The answer is \"" + magicWord 
       + "\".)"; 
     Object[] array = {msgString1, msgString2, textField}; 

     //Create an array specifying the number of dialog buttons 
     //and their text. 
     Object[] options = {btnString1, btnString2}; 

     //Create the JOptionPane. 
     optionPane = new JOptionPane(array, 
       JOptionPane.QUESTION_MESSAGE, 
       JOptionPane.YES_NO_OPTION, 
       null, 
       options, 
       options[0]); 

     //Make this dialog display it. 
     setContentPane(optionPane); 

     //Handle window closing correctly. 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 

     //Ensure the text field always gets the first focus. 
     addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentShown(ComponentEvent ce) { 
       textField.requestFocusInWindow(); 
      } 
     }); 

     //Register an event handler that puts the text into the option pane. 
     textField.addActionListener(this); 

     //Register an event handler that reacts to option pane state changes. 
     optionPane.addPropertyChangeListener(this); 
     pack(); 
    } 

    /** 
    * This method handles events for the text field. 
    */ 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     optionPane.setValue(btnString1); 
    } 

    /** 
    * This method reacts to state changes in the option pane. 
    */ 
    @Override 
    public void propertyChange(PropertyChangeEvent e) { 
     String prop = e.getPropertyName(); 

     if (isVisible() 
       && (e.getSource() == optionPane) 
       && (JOptionPane.VALUE_PROPERTY.equals(prop) 
       || JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) { 
      Object value = optionPane.getValue(); 

      if (value == JOptionPane.UNINITIALIZED_VALUE) { 
       //ignore reset 
       return; 
      } 

      //Reset the JOptionPane's value. 
      //If you don't do this, then if the user 
      //presses the same button next time, no 
      //property change event will be fired. 
      optionPane.setValue(
        JOptionPane.UNINITIALIZED_VALUE); 

      if (btnString1.equals(value)) { 
       typedText = textField.getText(); 
       String ucText = typedText.toUpperCase(); 
       if (magicWord.equals(ucText)) { 
        JOptionPane.showMessageDialog(this, "Correct answer given"); 
        exit(); 
       } else { 
        //text was invalid 
        textField.selectAll(); 
        JOptionPane.showMessageDialog(this, 
          "Sorry, \"" + typedText + "\" " 
          + "isn't a valid response.\n" 
          + "Please enter " 
          + magicWord + ".", 
          "Try again", 
          JOptionPane.ERROR_MESSAGE); 
        typedText = null; 
        textField.requestFocusInWindow(); 
       } 
      } else { //user closed dialog or clicked cancel 
       JOptionPane.showMessageDialog(this, "It's OK. " 
         + "We won't force you to type " 
         + magicWord + "."); 
       typedText = null; 
       exit(); 
      } 
     } 
    } 

    /** 
    * This method clears the dialog and hides it. 
    */ 
    public void exit() { 
     dispose(); 
    } 

    public static void main(String... args) { 
     //create JDialog and components on EDT 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new CustomDialog(null, "David").setVisible(true); 
      } 
     }); 
    } 
} 
+1

그래, 그게 내가 찾고 있던 것입니다. 고마워요! – bioMind

+0

완벽! 변경을 권장하는 유일한 방법은'optionPane.addPropertyChangeListener ("value", this);'를 사용하여 성능을 향상시키는 것입니다. – Daniel

+1

+1 왜냐하면 ... 덕분에 데이빗. 그것이 약간 다르며 유용 할 수도 있기 때문에 나는 아래에 광산을 게시했다. – PMorganCA

0

Stop Automatic Dialog Closing에 대한 한 가지 사실은 닫히지 않거나 유효성을 확인한 다음 닫으려는 경우에만 도움이된다는 것입니다.이 튜토리얼의 샘플 코드에 대한 해결책을 기반으로하면 유효성 검사가 실패하면 유효성을 검사하고 열어 둘 수 없습니다.

는 돌이켜 보면, 나는 그것이 JOptionPanel.createDialog을 사용하기 때문에 작동하지 않았다 내 첫 번째 시도가 될 수있는 이유는() (예제 코드는하지 않았다 무엇을) 생각합니다. 어쩌면 JOptionPanel이 자신의 JDialog를 만들어서 이벤트 처리가 어떻게 작동하는지에 대한 "백그라운드"의존성을 설정하게 할 수 있습니다. 어쨌든 나는 지금 원하는 것을 얻었습니다. David Kroucamp의 코드는 나에게 매우 유용했습니다. 그것은 다윗과 다르게 PropertyChangeListener를 처리하기 때문에 어떤 사람들에게 도움이 될 수 있도록

나는, 내 솔루션을 게시하도록하겠습니다. 당신은 코드의 대부분은 파일 실존에 대한

이 클래스를 확인 그의 (감사 데이빗) 동일 사용자가 새 이름을 제공하거나 취소 할 수 있음을 확인할 수 있습니다.생성자에서 사용자의 입력을 검증하는 데 사용하는 몇 가지 인수가 필요합니다. 검증이 if(!Files.exists(rootPathArg.resolve(input))) { // close the dialog }

class GetPathNameDialog extends JDialog implements ActionListener, PropertyChangeListener { 

    /** 
    * contains the users input 
    */ 
    private JTextField textField; 
    /** 
    * the option pane that holds all fields and controls in this dialog 
    */ 
    private JOptionPane optionPane; 
    /** 
    * label for the left button that represents "OK" 
    */ 
    private String button1Str; 
    /** 
    * label for the right button that represents "Cancel" 
    */ 
    private String button2Str; 
    /** 
    * path containing the named entity to be renamed. 
    */ 
    private Path rootPath; 

    /** 
    * Creates the reusable dialog. 
    */ 
    /** 
    * Creates the dialog, panel and all GUI components, sets up listeners. 
    * 
    * @param rootPath the path where the file or folder we are renaming lives 
    * @param initialText the initial text to display in the text field (i.e. current name) 
    * @param title title of the JDialog itself 
    * @param textFieldWidth number of columns in the JTextField that will contain the file/folder name 
    * @param promptStr the propmt to display in the panel 
    * @param button1Str the label for the "OK" button 
    * @param button2Str the label for the "Cancel" button 
    */ 
    public GetPathNameDialog(Path rootPath, String initialText, String title, int textFieldWidth, String promptStr, String button1Str, String button2Str) { 

     super((Frame) null, true); 

     // init class variables 
     this.rootPath = rootPath; 
     this.button1Str = button1Str; 
     this.button2Str = button2Str; 

     setTitle(title); 

     textField = new JTextField(textFieldWidth); 
     textField.setText(initialText); 

     //Create an array of the text and components to be displayed. 
     Object[] array = {promptStr, textField}; 

     //Create an array specifying the number of dialog buttons 
     //and their text. 
     Object[] options = {button1Str, button2Str}; 

     //Create the JOptionPane. 
     optionPane = new JOptionPane(
       array, 
       JOptionPane.QUESTION_MESSAGE, 
       JOptionPane.YES_NO_OPTION, 
       null, 
       options, 
       options[0]); 

     //Make this dialog display it. 
     setContentPane(optionPane); 

     //Handle window closing correctly. 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 

     //Ensure the text field always gets the first focus. 
     addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentShown(ComponentEvent ce) { 
       textField.requestFocusInWindow(); 
      } 
     }); 

     // Register an event handler that puts the text into the option pane INPUT_VALUE_PROPERTY 
     textField.addActionListener(this); 

     // Register an event handler that reacts to option pane state changes. 
     optionPane.addPropertyChangeListener(this); 

     // tell this dialog to display close to the current mouse pointer 
     setLocation(MouseInfo.getPointerInfo().getLocation()); 
     pack(); 
    } 

    /** 
    * This method handles events for the text field. 
    */ 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     // this will fire a INPUT_VALUE_PROPERTY PropertyChangeEvent... takes the user input to the validaton code in the property handler 
     optionPane.setInputValue(textField.getText()); 
    } 

    /** 
    * This method reacts to property changes. 
    */ 
    @Override 
    public void propertyChange(PropertyChangeEvent e) { 

     String prop = e.getPropertyName(); 

     if (isVisible() && (e.getSource() == optionPane)) { 

      // the VALUE_PROPERTY is not the same as the INPUT_VALUE_PROPERTY. we make use of the INPUT_VALUE_PROPERTY to carry our data 
      // but the JOptionPane uses the VALUE_PROPERTY for other stuff 
      if (JOptionPane.VALUE_PROPERTY.equals(prop)) { 
       // newValues delivered by VALUE_PROPERTY PropertyChangeEvent can be the actual labels of the button clicked, 
       // that's sooo counter-intuitive to me, but it's how we know which button got clicked 
       if (button1Str.equals(e.getNewValue())) { 
        // "OK" functionality... 
        // ...this will fire the event that takes the user input to the validation code 
        optionPane.setInputValue(textField.getText()); 
       } else if (button2Str.equals(e.getNewValue())) { 
        // "CANCEL" functionality 
        optionPane.setInputValue(null); 
        exit(); 
       } 

      } else if (JOptionPane.INPUT_VALUE_PROPERTY.equals(prop)) { 

       Object value = optionPane.getInputValue(); 

       // null or empty strings in the text field (ie in the INPUT_VALUE_PROPERTY) are ignored 
       if (null != value && ((String) value).length() > 0) { 
        // here is the validation code 
        if (Files.exists(rootPath.resolve(textField.getText()))) { 
         // already exists, tell user 
         JOptionPane.showMessageDialog(this, 
           "Sorry, " + rootPath.resolve(textField.getText()).toString() + " already exists.\n\n Please enter another name.", 
           "OK", 
           JOptionPane.ERROR_MESSAGE); 
         // Make sure PropertyChangeEvent will fire next time... 
         // ...PropertyChangeEvents don't fire in setInputValue(newVal)... 
         // ...if newVal is equal to the current value, but if the user clicks... 
         // ...button 1 or hits enter in the text field without changing his text,... 
         // ...we still want to fire another event... 
         // ...so we reset the property without changing the text in the textField 
         optionPane.setInputValue(null); 
        } else { 
         // does not exist.. we are keeping the users input... 
         // ... it gets delivered to the user in getInputValue() 
         exit(); 
        } 
       } 
      } 
     } 
    } 

    /** 
    * returns the users's validated input. Validated means !Files.exists(rootPath.resolve(input)). 
    * 
    * @return the text entered by the user, UNINITIALIZED_VALUE if the user X closed, null the user canceled 
    */ 
    public Object getInputValue() { 
     return optionPane.getInputValue(); 
    } 

    /** 
    * closes the dialog and triggers the return from setVisible() 
    */ 
    public void exit() { 
     dispose(); 
    } 
} 

코드 호출입니다 그것이 :

당신이 사용하는 어떤 방법
GetPathNameDialog tempD = new GetPathNameDialog(
         someFolderPath, 
         "theFileNameThatMustBeChanged.txt", 
         "Change File Name", 
         50, 
         "someFolderPath already contains a file named theFileNameThatMustBeChanged.txt." + ".\n\nPlease enter a different file name:", 
         "Copy the file with the new name", "Do not copy the file"); 
    tempD.setVisible(true); 

    Object inputObj = tempD.getInputValue(); 
    String input = (inputObj == JOptionPane.UNINITIALIZED_VALUE || null == inputObj ? "" : (String) inputObj); 

    if (input.length() > 0) { 
     // we now have a new file name. go ahead and do the copy or rename or whatever... 
    } 
+0

* 유효성 검사가 실패한 경우 유효성 검사를받지 못했습니다. * 음 ... 확실하지 않은 내용이 무엇인지 확실하지 않습니다. –

+0

@DavidKroukamp @DavidKroukamp 코드가 제대로 작동 했으므로 혼란 스럽습니다. 내가 할 수 없었던 것은 자바 튜토리얼에서 예제 코드의 일부분을 잘라내어 붙여 넣기로 한 원래 시도였다. – PMorganCA

관련 문제