# Frage zu SwingUtilities.invokeLater



## Gast2 (12. Mrz 2009)

Hall zusammen,

ich hab mal wieder ein Problem mit  SwingUtilities.invokeLater und versteh es nicht so ganz.Erstmal die Helper Klasse welche benutzt wird.
[HIGHLIGHT="Java"]
public class ErrorHelper {

 public static void showError(Component owner, String titleKey, Exception exception) {
        Window window;
        if (owner != null) {
            window = SwingUtilities.getWindowAncestor(owner);
            owner = window != null ? window : owner;
        }

JXErrorPane.showDialog(owner, createErrorInfo(titleKey, exception));

    }

    public static void showError(Component owner, Exception exception) {
        showError(owner, "errordialog.title", exception);
    }


[/HIGHLIGHT]

Also wenn ich folgenden Code ausführe wir der Fehlerdialog nur einmal geöffnet und das Error auch nur einmal auf der Konsole ausgegben
[HIGHLIGHT="Java"]

public void actionPerfomed(ActionEvent e){
     try {
             //some stuff
            } catch (final Exception e) {
                System.out.println("Error");
                SwingUtilities.invokeLater(new Runnable(){
                    public void run() {
                        ErrorHelper.showError(errorReferenceComponent, e);
                    }

                }); 
            }
}
[/HIGHLIGHT]

bei diesem code hingegen wird der fehlerdialog 2 mal angezeigt genauso das error auf der konsole... 
[HIGHLIGHT="Java"]
public void actionPerfomed(ActionEvent e){
     try {
             //some stuff
            } catch (final Exception e) {
                System.out.println("Error");
                ErrorHelper.showError(errorReferenceComponent, e);

            }
}
[/HIGHLIGHT]

Kann mir jemand erklären warum???;(


----------



## Gast2 (12. Mrz 2009)

ahhhh jetzt nach langem suchen blick ich die sache =)...
vielleicht weiß jemand eine gute lösung...

ich hab ein textfeld das soll auf änderungen von return,tab, und focus lost reagieren...
gibt es da einen geeigneten listener dafür?
wenn dieses event passiert dann überpüft er die eingegeben daten und wirft eine exception und daraufhin wird der error angezeigt.
Die bisherige Lösung war ein ActionListener und ein FocusListener, was da aber das problem war wenn man return drückt und ein fehler angezeigt wird(focus) dann hat man 2 mal das gleiche event... und das will ich irgendwie umgehen...


----------



## Marco13 (12. Mrz 2009)

Kannst mal nach DocumentListener suchen. Irgendein Flag "isCurrentlyShowingDialog" oder so wäre vielleicht ein Workround, aber das sollte nicht notwendig sein...


----------



## Gast2 (12. Mrz 2009)

okay versuch ich mal... besser als nichts =)...
weiß sonst noch jemand eine gute lösung für return und focuslost???

EDIT: DocumentListener??? Leider finde ich dazu nichts =(


----------



## hdi (12. Mrz 2009)

DocumentListener (Java Platform SE 6)


----------



## Gast2 (12. Mrz 2009)

hehe ja schon klar, aber ich finde das flag nicht


----------



## Ebenius (17. Mrz 2009)

Ich glaub, jetzt weiß ich was Du suchst: JComponent.setInputVerifier(InputVerifier)

Ebenius


----------



## Gast2 (17. Mrz 2009)

ich hab einen Listener gesucht der auf focusLost und auf actionPerformed reagiert...
Das problem war folgendes man schreibt einen Wert in ein Textfeld, der Wert wird erst im Model übernommen, wenn enter(oder Speicher Button) gedrückt wurde jetzt wollte ich dass gleiche auch machen wenn das textfeld den focus verliert...
so problem ist wenn ich nun enter drück und es passiert ein fehler wird ein Fehlerdialog angezeigt, was gleichzeitig für das textfeld wieder ein focusLost bedeutet (bevor die actionPerformed methode fertig ist) und diese wiederum ein Fehlerdialog hoch popt, da das focusLost ein rekursiven aufruf macht, darum werden 2 gleiche Fehlerdialoge hintereinander angezeigt...

mit dem InputVerifier ist das problem halt wenn man eine falsche eingabe macht kommt man aus dem feld heraus und MUSS das richtige eingeben wenn der User aber nicht weiß was er eingeben soll oder merkt er hat was vergessen und die Aktion abbrechen möchte kommt er halt nicht mehr aus dem textfeld heraus... find ich net ganz praktikabel


----------



## Gast2 (17. Mrz 2009)

Hier ein Beispiel
[HIGHLIGHT="Java"]

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

public class VerifierTest extends JFrame {

    public VerifierTest() {
        JTextField tf1 = new JTextField("Type \"pass\" here");
        getContentPane().add(tf1, BorderLayout.NORTH);
        tf1.setInputVerifier(new PassVerifier());
        tf1.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                JTextField tf = (JTextField) e.getSource();
                if (!"pass".equals(tf.getText())) {
                    System.out.println("Fehler");
                    JOptionPane.showMessageDialog(tf, "Fehler.", "Error", JOptionPane.ERROR_MESSAGE);

                }

            }

        });
        JTextField tf2 = new JTextField("TextField2");
        getContentPane().add(tf2, BorderLayout.SOUTH);

        WindowListener l = new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        };
        addWindowListener(l);
    }

    class PassVerifier extends InputVerifier {

        public boolean verify(JComponent input) {
            JTextField tf = (JTextField) input;
            tf.postActionEvent();

            return true;
        }
    }

    public static void main(String[] args) {
        Frame f = new VerifierTest();
        f.pack();
        f.setVisible(true);
    }
}

}

[/HIGHLIGHT]

einfahc enter drücken dann popt der dialog 2 mal hoch...
das gleiche passier auch wenn man einen focuslistener verwendet...


----------



## Ebenius (17. Mrz 2009)

SirWayne hat gesagt.:


> mit dem InputVerifier ist das problem halt wenn man eine falsche eingabe macht kommt man aus dem feld heraus und MUSS das richtige eingeben wenn der User aber nicht weiß was er eingeben soll oder merkt er hat was vergessen und die Aktion abbrechen möchte kommt er halt nicht mehr aus dem textfeld heraus... find ich net ganz praktikabel


Stimmt so nicht; das hängt doch vom Verifier ab, den Du selber baust. [HIGHLIGHT="Java"]static void checkTextFieldText(final JTextField textField) {
  if ("Richtig".equals(textField.getText())) {
    textField.setBackground(Color.GREEN);
  } else {
    textField.setBackground(Color.RED);
    JOptionPane.showMessageDialog(textField, "\"Richtig\" eingeben!");
  }
}

public static void main(String[] args) {
  final JTextField textField = new JTextField(25);
  textField.setText("Richtig");
  textField.setBackground(Color.GREEN);

  textField.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
      checkTextFieldText((JTextField) e.getSource());
    }

  });
  textField.setInputVerifier(new InputVerifier() {

    @Override
    public boolean verify(JComponent input) {
      checkTextFieldText(textField);
      return true;
    }
  });

  final JPanel panel = new JPanel(new BorderLayout(6, 6));
  panel.add(textField, BorderLayout.CENTER);
  panel.add(new JButton("Focusable Dummy"), BorderLayout.SOUTH);

  final JFrame f = new JFrame("Input Verifier Fun");
  f.setContentPane(new JScrollPane(panel));
  f.pack();
  f.setLocationRelativeTo(null);
  f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  f.setVisible(true);
}[/HIGHLIGHT]

EDIT: Ich hab das Zitat grad nochmal versucht zu verstehen. Mit jedem Lesen wird das unklarer... Was wolltest Du damit eigentlich sagen?

Ebenius


----------



## Ebenius (17. Mrz 2009)

Noch ein Hinweis am Rande: [HIGHLIGHT=Java]WindowListener l = new WindowAdapter() {

  public void windowClosing(WindowEvent e) {
    System.exit(0);
  }
};
addWindowListener(l);[/HIGHLIGHT]
... kann man super ersetzen durch: [HIGHLIGHT=Java]setDefaultCloseOperation(EXIT_ON_CLOSE);[/HIGHLIGHT]
Ebenius


----------



## Gast2 (17. Mrz 2009)

ja das weiß ich =)... hab das Bsp. oben aus der API rauskopiert und ergänzt--> war zu faul ...

Vergess mein oberes zitat hab gemerkt dass wenn ich immer return true zurück gebe, das Focus Problem weg ist.

aber zu deinem Bsp. macht genau das gleiche wie meines.

Nimm einen falschen Wert und drück enter(führ die actionPerformed() methode aus)...
Dann kommt der Message Dialog 2 mal --> das ist das problem...
weil bevor die actionPerformed() methode fertig(genau da wo der andere Dialog kommt) ist wird mittendrin ein focusLost event geschmissen, was zu folge hat dass die verfiy methode aufgerufen wird und wir dann rekursiven aufruf haben...


----------



## Ebenius (17. Mrz 2009)

SirWayne hat gesagt.:


> aber zu deinem Bsp. macht genau das gleiche wie meines.


Ja. Hab Dein Beispiel erst gesehen, nachdem ich meines gepostet hatte. 



SirWayne hat gesagt.:


> Nimm einen falschen Wert und drück enter(führ die actionPerformed() methode aus)...
> Dann kommt der Message Dialog 2 mal --> das ist das problem...
> weil bevor die actionPerformed() methode fertig(genau da wo der andere Dialog kommt) ist wird mittendrin ein focusLost event geschmissen, was zu folge hat dass die verfiy methode aufgerufen wird und wir dann rekursiven aufruf haben...


Das kann ich auf meinem System (Linux / KDE) weder mit Deinem noch mit meinem Beispiel nachvollziehen ???:L. Ich tippe (bei meinem Beispiel) "falsch" ein, drücke Enter, dann kommt der Dialog hoch. Getestet hab ich das eben mit JRE 6_10, JRE 6_7 und JRE 5_12.

EDIT: Ahhhh. Mit JRE 1.4.2_13 kann ich das nachvollziehen; StackOverflow! 

Ebenius


----------



## Ebenius (17. Mrz 2009)

Ebenius hat gesagt.:


> EDIT: Ahhhh. Mit JRE 1.4.2_13 kann ich das nachvollziehen; StackOverflow!


Wenn Du in meinem Beispiel die checkTextFieldText()-Methode so änderst, passiert's nicht mehr: [HIGHLIGHT="Java"]static void checkTextFieldText(final JTextField textField) {
  if ("Richtig".equals(textField.getText())) {
    textField.setBackground(Color.GREEN);
  } else {
    textField.setBackground(Color.RED);
    final InputVerifier inputVerifier = textField.getInputVerifier();
    try {
      textField.setInputVerifier(null);
      JOptionPane.showMessageDialog(textField, "\"Richtig\" eingeben!");
    } finally {
      textField.setInputVerifier(inputVerifier);
    }
  }
}[/HIGHLIGHT]
Ebenius


----------



## Gast2 (17. Mrz 2009)

heeee ??? Stack overflow???? des hab ich noch gar nicht hinbekommen =)
 Nee bei mir kommt einfach 2 mal der message dialog ...
find ich auch logisch !!! actionPerfomed()-->ruft message dialog auf-->focusLost-->verify -->die sache nochmal....
versucht jre 1.6_11 und jdk 1.5_17 unter XP...


----------



## Ebenius (17. Mrz 2009)

SirWayne hat gesagt.:


> heeee ??? Stack overflow???? des hab ich noch gar nicht hinbekommen =)


Java 1.4, dazu gab's auch nen Sun-Bug, hab ich aber vergessen.



SirWayne hat gesagt.:


> Nee bei mir kommt einfach 2 mal der message dialog


Ich auch; passiert bei mir trotzdem nicht. Was ist mit der Änderung in meinem Letzten Beitrag? Funktioniert's damit dann bei Dir wie gewünscht?

Ebenius


----------



## Gast2 (17. Mrz 2009)

Habs grad versucht... Klappt gut mit einem FocusListener würde es nicht funktionieren weil den kann man nicht auf null setzen... gefällt mir die lösung sieht sauberer aus wie meine jetzige =)... 

dank dir


----------

