2013-07-24 2 views
5

Ho un problema con un'applicazione Swing in cui a volte è possibile ottenere la messa a fuoco da un campo di immissione testo per motivi che non sono attualmente in grado di identificare. Sospetto una condizione di gara di qualche tipo ma non riesco a vedere cosa sta causando l'evento di messa a fuoco.Identificazione dell'origine di una richiesta di messa a fuoco nell'interfaccia utente Java Swing

Il campo ha un listener di messa a fuoco collegato ad esso in modo che sia semplice aggiungere un punto di interruzione al gestore di eventi focusGained(). Quando lo faccio, posso vedere l'evento sottostante che a sua volta contiene un'istanza di CausedFocusEvent.Cause. Il campo del nome è impostato su "ATTIVAZIONE".

Guardando la traccia dello stack, posso vedere il seguente:

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 174 in MyPanel$3)) 
    MyPanel$3.focusGained(FocusEvent) line: 174 
    AWTEventMulticaster.focusGained(FocusEvent) line: not available 
    InputField(Component).processFocusEvent(FocusEvent) line: not available 
    InputField(Component).processEvent(AWTEvent) line: not available  
    InputField(Container).processEvent(AWTEvent) line: not available  
    InputField(Component).dispatchEventImpl(AWTEvent) line: not available 
    InputField(Container).dispatchEventImpl(AWTEvent) line: not available 
    InputField(Component).dispatchEvent(AWTEvent) line: not available 
    DefaultKeyboardFocusManager(KeyboardFocusManager).redispatchEvent(Component, AWTEvent) line: not available 
    DefaultKeyboardFocusManager.typeAheadAssertions(Component, AWTEvent) line: not available  
    DefaultKeyboardFocusManager.dispatchEvent(AWTEvent) line: not available 
    InputField(Component).dispatchEventImpl(AWTEvent) line: not available 
    InputField(Container).dispatchEventImpl(AWTEvent) line: not available 
    InputField(Component).dispatchEvent(AWTEvent) line: not available 
    SunToolkit$1.run() line: not available 
    PeerEvent(InvocationEvent).dispatch() line: not available 
    EventQueue.dispatchEventImpl(AWTEvent, Object) line: not available 
    EventQueue.access$200(EventQueue, AWTEvent, Object) line: not available 
    EventQueue$3.run() line: not available 
    EventQueue$3.run() line: not available 
    AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]  
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: not available 
    EventQueue.dispatchEvent(AWTEvent) line: not available 
    EventDispatchThread.pumpOneEventForFilters(int) line: not available 
    EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: not available 
    EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: not available 
    EventDispatchThread.pumpEvents(int, Conditional) line: not available  
    EventDispatchThread.pumpEvents(Conditional) line: not available 
    EventDispatchThread.run() line: not available 

Nota che inputfield è una sottoclasse di JTextField che con lievi modifiche relative al rendering del testo.

Tutto quello che posso dire dalla traccia dello stack è che qualcosa sull'EDT ha causato l'attivazione del campo di immissione in MyPanel.

C'è qualche ulteriore informazione che posso ottenere che mi dia visibilità sul perché l'attenzione è stata acquisita da questo componente?

+1

Non dovrebbe esserci alcuna condizione di competizione poiché tutti gli eventi Swing dovrebbero essere eseguiti su un singolo thread, l'EDT. Potresti provare a isolare il codice che causa il problema tagliando il codice fino a quando il problema non si risolve, cercando in tal modo di trovare il codice minimale che riproduce il problema e quindi pubblicarlo qui. Curioso però: per cosa stai usando FocusListener? –

+1

Sono d'accordo sul thread singolo, ma la mia preoccupazione è che swing possa eseguire il rendering sottostante in un ordine non deterministico e che qualcosa inavvertitamente dipenda da quell'ordine. L'ascoltatore di messa a fuoco è principalmente solo per il debug, non ha alcuna influenza su quando si acquisisce lo stato attivo, semplicemente reagisce ad esso. – PhilDin

+1

'è che qualcosa sull'EDT ha causato l'inputfield in MyPanel per ottenere il focus. Per favore causato da ???, per un aiuto migliore prima pubblicare un SSCCE, breve, eseguibile, compilabile, causato problema con focusGained da InputField reindirizzato dall'eccezione JVM a MyPanel – mKorbel

risposta

0

Ho avuto un problema simile,

alla fine ho appena specificato la gerarchia messa a fuoco e preso tutto il controllo sulla messa a fuoco da Java. Va un po 'di qualcosa di simile:

// Setting The FOCUS Order. 
    Vector<Component> order = new Vector<Component>(7); 
    order.add(projectNameJTextField); 
    order.add(companyJTextField); 
    order.add(orderedByJTextField); 
    order.add(phoneJTextField); 
    order.add(jRadioNormalPriority); 
    order.add(jRadioHighPriority); 
    order.add(jCheckBox1); 
    order.add(jCheckBox2); 
    order.add(jCheckBox3); 
    order.add(jCheckBox4); 
    order.add(jCheckBox5); 
    order.add(jCheckBox6); 
    order.add(textDetailJTextArea); 
    order.add(technitianJComboBox); 
    order.add(aproxTimeJTextField); 
    order.add(sendButton); 

    // Sending the costume focus order to the focus Policy Class, 
    MyOwnFocusTraversalPolicy newPolicy = new MyOwnFocusTraversalPolicy(order); 
    setFocusTraversalPolicy(newPolicy); 

e avrete anche bisogno di questo Classe:

import java.awt.Component; 
    import java.awt.Container; 
    import java.awt.FocusTraversalPolicy; 
    import java.util.Vector; 



    // This Class Helps to Set A Costume FOCUS Order. 
    public class MyOwnFocusTraversalPolicy extends FocusTraversalPolicy 
    { 
    Vector<Component> order; 

    public MyOwnFocusTraversalPolicy(Vector<Component> order) { 
     this.order = new Vector<Component>(order.size()); 
     this.order.addAll(order); 
    } 
    public Component getComponentAfter(Container focusCycleRoot, 
             Component aComponent) 
    { 
     int idx = (order.indexOf(aComponent) + 1) % order.size(); 
     return order.get(idx); 
    } 

    public Component getComponentBefore(Container focusCycleRoot, 
             Component aComponent) 
    { 
     int idx = order.indexOf(aComponent) - 1; 
     if (idx < 0) { 
      idx = order.size() - 1; 
     } 
     return order.get(idx); 
    } 

    public Component getDefaultComponent(Container focusCycleRoot) { 
     return order.get(0); 
    } 

    public Component getLastComponent(Container focusCycleRoot) { 
     return order.lastElement(); 
    } 

    public Component getFirstComponent(Container focusCycleRoot) { 
     return order.get(0); 
    } 
    } 

(questa non è la mia soluzione, e non ricordo dove l'ho preso da)

Speranza ho potuto fare :)

Dave.

+0

_ "Non ricordo da dove l'ho preso" _ - Forse direttamente dall'esempio [tutorial] (http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle .com/javase/tutorial/uiswing/examples/misc/FocusTraversalDemoProject/src/misc/FocusTraversalDemo.java) ;-) –

+0

right :) grazie per avermelo ricordato :) –