2012-06-18 5 views
1

У меня есть несколько текстовых полей, которые я накладываю между ними. На focusLost() Я открываю JOptionPane. Я хотел бы, чтобы код в focusGained() был выполнен ПОСЛЕ JOptionPane был закрыт. Несмотря на то, что диалог является модальным, focusGained() вызывается до закрытия JOptionPane. Есть ли способ обойти это?Как подождать, когда JOptionPane будет закрыт, прежде чем отправлять какие-либо события

Обнаружил этот вопрос, но он, похоже, не был разрешен. Postpone Event Queue after Focus Lost

Вот пример кода. Вы заметите, что «Focus Gained» напечатано до закрытия JOptionPane.

import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 

public class ShortTest implements FocusListener 
{ 
private void go() 
{ 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    JPanel panel = new JPanel(); 
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 

    JTextField text1 = new JTextField(); 
    text1.setName("text1"); 
    text1.addFocusListener(this); 

    JTextField text2 = new JTextField(); 
    text2.setName("text2"); 
    text2.addFocusListener(this); 

    panel.add(new JLabel("tex1")); 
    panel.add(text1); 

    panel.add(new JLabel("text2")); 
    panel.add(text2); 

    frame.setContentPane(panel); 
    frame.pack(); 
    frame.setVisible(true); 
} 

public static void main(String [] args) 
{ 
    ShortTest test = new ShortTest(); 
    test.go(); 
} 

@Override 
public void focusGained(FocusEvent e) 
{ 
    if (!e.isTemporary() && (e.getSource() instanceof JTextField)) 
    { 
     System.out.println("Focus Gained: " + ((JTextField)e.getSource()).getName()); 
    } 
} 

@Override 
public void focusLost(FocusEvent e) 
{ 
    if (!e.isTemporary() && (e.getSource() instanceof JTextField)) 
    { 
     JOptionPane.showOptionDialog(null, ((JTextField)e.getSource()).getName() + " lost focus", "Title", JOptionPane.DEFAULT_OPTION, 0, null, null, null); 
    } 
} 
} 
+0

Рассмотрите возможность создания и публикации [SSCCE] (http://SSCCE.org), которую мы можем запускать и изменять, и которая демонстрирует вашу проблему. –

+0

См. Редактирование моего ответа. 1+ для публикации sscce - очень впечатляет! –

ответ

3

Возможно, что вы хотите, это не фокус слушателя (конструкция очень низкого уровня), а входной верификатор (более высокий уровень конструкт). Это должно реагировать до того, как фокус сдвинулся. Например, в приведенном ниже коде верификатор реагирует, если пользователь пытается ввести нечисловые данные в текстовое поле. Да, это также можно сделать с помощью DocumentFilter.

import javax.swing.*; 

public class VerifierEg extends JPanel { 
    private static final int FIELD_COUNT = 3; 

    public VerifierEg() { 
     InputVerifier inputVerifier = new InputVerifier() { 

     @Override 
     public boolean verify(JComponent input) { 
      final JTextField textField = (JTextField) input; 
      String text = textField.getText(); 
      for (char c : text.toCharArray()) { 
       if (!Character.isDigit(c)) { 
        textField.setText(""); 
        JOptionPane.showMessageDialog(VerifierEg.this, "Text: \"" 
         + text + "\" must hold only digits", "Text Field Error", 
         JOptionPane.ERROR_MESSAGE); 
        return false; 
       } 
      } 
      return true; 
     } 
     }; 
     for (int i = 0; i < FIELD_COUNT; i++) { 
     JTextField field = new JTextField(6); 

     field.setInputVerifier(inputVerifier); 
     add(field); 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("Enter Numbers"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new VerifierEg()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

Edit:
InputVerifier может работать для вашей цели, даже если вы не проверки входа в каком-либо определенном образе. Например, чтобы изменить код:

import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import javax.swing.BoxLayout; 
import javax.swing.InputVerifier; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 

public class ShortTest2 { 
    private void go() { 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel panel = new JPanel(); 
     panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 

     InputVerifier inputVerifier = new InputVerifier() { 

     @Override 
     public boolean verify(JComponent input) { 
      JOptionPane.showMessageDialog(frame, 
        "Focus Lost on " + input.getName()); 
      return true; 
     } 
     }; 

     FocusListener focusListener = new FocusListener() { 

     @Override 
     public void focusLost(FocusEvent e) { 
      String name = ((JComponent)e.getSource()).getName(); 
      System.out.println("Focus Lost: " + name); 
     } 

     @Override 
     public void focusGained(FocusEvent e) { 
      String name = ((JComponent)e.getSource()).getName(); 
      System.out.println("Focus Gained: " + name); 
     } 
     }; 

     JTextField[] textFields = new JTextField[2]; 
     for (int i = 0; i < textFields.length; i++) { 
     JTextField textField = new JTextField(10); 
     String name = "text " + (i + 1); 
     textField.setName(name); 
     textField.setInputVerifier(inputVerifier); 
     textField.addFocusListener(focusListener); 

     panel.add(new JLabel(name)); 
     panel.add(textField);   
     } 

     frame.setContentPane(panel); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     ShortTest2 test = new ShortTest2(); 
     test.go(); 
    } 
} 

1+ для вашего SSCCE, кстати!

+0

+1 для go, +100 для InputVerifier – mKorbel

+0

Спасибо за вашу помощь и предложения. Хотя мне действительно нужно использовать JOptionPane во время фокусных событий (и событий мыши и других случаев на EDT), это может помочь кому-то другому. В двух словах оба focusGained() и focusLost() изменяли одну и ту же переменную, но я не ожидал, что focusGained() изменит ее до тех пор, пока функция focusLost() не вернется. Сначала я решил, что решение будет состоять в том, чтобы focusLost возвращался до того, как был введен focusGained(), но в итоге я просто сохранил копию переменной в начале focusGained() и вернул эту копию, когда focusGained() закончен. – Amber