2015-05-26 17 views
7

sto ricevendo un'eccezione e non capisco che cosa la causa. È un'app FX con file FXML. Nella parte init() dell'app aggiungo un listener a un campo di testo che chiama una funzione che monitora la stringa con un'espressione regolare per un pattern.JavaFX Il campo di testo con listener fornisce: "java.lang.IllegalArgumentException: L'avvio deve essere <= la fine"

tf.textProperty().addListener(
     (observable, oldValue, newValue) -> { 
      handleInput(newValue); 
     }); 

la funzione:

private void handleInput(String s) { 

      s = s.toUpperCase(); 
      Matcher matcher = Pattern 
        .compile(
          "^[A-Z]{2}(20|21|22|23|[0-1]\\d)[0-5]\\d(20|21|22|23|[0-1]\\d)[0-5]\\d(T\\s|C\\s|TC|CT|\\s\\s)$") 
        .matcher(s); 

      if (matcher.find()) { 

        // do something 

        // then clear the textfield 
        tf.clear(); 

       } else { 
        // do something else 
       } 
      } 

Funziona ma mi dà un'eccezione nel caso in cui il matcher partite.

L'eccezione:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: The start must be <= the end 
    at javafx.scene.control.TextInputControl.getText(Unknown Source) 
    at javafx.scene.control.TextInputControl.updateContent(Unknown Source) 
    at javafx.scene.control.TextInputControl.replaceText(Unknown Source) 
    at com.sun.javafx.scene.control.skin.TextFieldSkin.replaceText(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.TextFieldBehavior.replaceText(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.defaultKeyTyped(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callActionForEvent(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase.lambda$new$75(Unknown Source) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase$$Lambda$88/1978656397.handle(Unknown Source) 
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source) 
    at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source) 
    at javafx.event.Event.fireEvent(Unknown Source) 
    at javafx.scene.Scene$KeyHandler.process(Unknown Source) 
    at javafx.scene.Scene$KeyHandler.access$1800(Unknown Source) 
    at javafx.scene.Scene.impl_processKeyEvent(Unknown Source) 
    at javafx.scene.Scene$ScenePeerListener.keyEvent(Unknown Source) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(Unknown Source) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$349(Unknown Source) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$349/1135388943.get(Unknown Source) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(Unknown Source) 
    at com.sun.glass.ui.View.handleKeyEvent(Unknown Source) 
    at com.sun.glass.ui.View.notifyKey(Unknown Source) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source) 
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source)} 

ho già provato alcuni suggerimenti che ho trovato qui in altri post, come per controllare la stringa prima di dare al matcher:

if (!tf.getText() == null) { 

o

if (!tf.getText().equals("") { 

ma l'eccezione rimane. Quando rimuovo:

tf.clear(); 

tutto funziona correttamente.

... qualche idea a qualcuno?

EDIT per la soluzione di swinkler:

eccezione con le fonti che provo quando utilizzando il codice di swinkler - JDK 1.8.0_45:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: The start must be <= the end 
    at javafx.scene.control.TextInputControl.getText(TextInputControl.java:446) 
    at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:564) 
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548) 
    at com.sun.javafx.scene.control.skin.TextFieldSkin.replaceText(TextFieldSkin.java:576) 
    at com.sun.javafx.scene.control.behavior.TextFieldBehavior.replaceText(TextFieldBehavior.java:202) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.defaultKeyTyped(TextInputControlBehavior.java:238) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(TextInputControlBehavior.java:139) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(BehaviorBase.java:218) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callActionForEvent(TextInputControlBehavior.java:127) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase.lambda$new$75(BehaviorBase.java:135) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase$$Lambda$91/476337053.handle(Unknown Source) 
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 
    at javafx.event.Event.fireEvent(Event.java:198) 
    at javafx.scene.Scene$KeyHandler.process(Scene.java:3965) 
    at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3911) 
    at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040) 
    at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2502) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:197) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:147) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$349(GlassViewEventHandler.java:228) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$142/181559839.get(Unknown Source) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:227) 
    at com.sun.glass.ui.View.handleKeyEvent(View.java:546) 
    at com.sun.glass.ui.View.notifyKey(View.java:956) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101) 
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source) 
    at java.lang.Thread.run(Thread.java:745) 
+0

Sembra che si sta aggiungendo un listener per quando il textProperty() delle variazioni del campo di testo. Se vuoi cambiare ciò che il testo dovrebbe avere mentre gestisci l'evento, dovresti farlo con il parametro 'new value' invece di usare' clear() ' –

+0

Mi piace avere il campo di testo pronto per un nuovo input una volta che la stringa ha abbinato al modello. Ho anche provato a usare tf.settext ("") invece di tf.clear(). Dà anche la stessa eccezione. – VictorRomeo

+0

Il punto è che non dovresti provare a modificare il testo nel campo perché sei nel mezzo della gestione dell'evento 'text modified'. Penso che il modo corretto è impostare il parametro 'newValue' su" ". –

risposta

0

non riesco a ottenere il vostro errore quando si utilizza questo in un semplice JavaFX applicazione. Ecco il codice che ho usato per testare la tua implementazione. Il mio input di prova è "AA20552055T" per corrispondere all'espressione regolare - il campo di testo viene cancellato.

Potete per favore confrontare con la soluzione:

public class JavaFXApplication1 extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); 
     Scene scene = new Scene(root); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

} 

La classe Controller con la logica:

public class FXMLDocumentController implements Initializable { 

    @FXML 
    private TextField textfield; 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     textfield.textProperty().addListener(
       (observable, oldValue, newValue) -> { 
        handleInput(newValue); 
       }); 
    } 

    private void handleInput(String s) { 

     s = s.toUpperCase(); 
     Matcher matcher = Pattern 
       .compile(
         "^[A-Z]{2}(20|21|22|23|[0-1]\\d)[0-5]\\d(20|21|22|23|[0-1]\\d)[0-5]\\d(T\\s|C\\s|TC|CT|\\s\\s)$") 
       .matcher(s); 

     if (matcher.find()) { 

        // do something 
        // then clear the textfield 
      textfield.clear(); 

     } else { 
      // do something else 
     } 
    } 
} 

Il file FXML:

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication1.FXMLDocumentController"> 
    <children> 
     <TextField layoutX="126" layoutY="150" fx:id="textfield" /> 
    </children> 
</AnchorPane> 

quanto riguarda il commento, ho installato JDK 1.8.0_45 (precedente alla 1.8.0_20) Utilizzo di Windows 7 x64 Ancora, nessun errore.

Here is the jar Netbeans crea automaticamente: l'ho testato da CMD. Funziona anche bene. Puoi testare se il file jar eseguito da CMD funziona correttamente sul tuo computer?

Per il debug - questo è il metodo in cui i dati di eccezione sono dati dal parametro change. modifica ha un start e end.

private void updateContent(TextFormatter.Change change, boolean forceNewUndoRecord) { 
     final boolean nonEmptySelection = getSelection().getLength() > 0; 
     String oldText = getText(change.start, change.end); 

I valori di inizio e fine quindi attivare l'eccezione in getText(...):

public String getText(int start, int end) { 
     if (start > end) { 
      throw new IllegalArgumentException("The start must be <= the end"); 
     } 

     if (start < 0 
      || end > getLength()) { 
      throw new IndexOutOfBoundsException(); 
     } 

     return getContent().get(start, end); 
    } 
+0

Grazie per l'esempio. Ho fatto un copia e incolla e ho ottenuto lo stesso errore (questa volta con le fonti, pubblicato di seguito. Ho dimenticato di implementare Initializable * ooops * - il tempo di fare una pausa.) - btw. sto usando JDK 1.8.0_45 – VictorRomeo

+0

@VictorRomeo: ho aggiunto alcune informazioni sull'ambiente. – swinkler

+0

grazie - ricevo un errore con il tuo .jar - screenshot qui: http://up.picr.de/22049687bw.jpg - qualche idea? – VictorRomeo

7

Ho avuto lo stesso problem e abbiamo trovato il bug report JDK-8081700, che ha risolto il problema. Non risulta un bug.

Il banco di prova tenta di modificare la proprietà di testo all'interno del cambiamento gestore. Questo non è supportato e i gestori di eventi di proprietà sono non rientranti.

Il modo corretto è per l'applicazione di ritardare la modifica, utilizzando runLater():

if (matcher.find()) { 
     System.err.println("true"); 
     Platform.runLater(() -> { 
      textField.clear(); 
     }); 
    }