如果用户将制表符粘贴到JavaFX中,则TextField
应用程序线程将引发StringIndexOutOfBoundsException
。我怎样才能聪明地防止用户以这种方式破坏我的应用程序呢?
下面是一个演示该行为的最小示例。
//Defined in Main.java
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
AnchorPane root = (AnchorPane) FXMLLoader
.load(getClass().getResource("MainView.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
在MainView.fxml中定义:
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextField fx:id="tf" />
</children>
</AnchorPane>
过程:
将制表符( clipboard
TextField
TextField
中的内容
无论用户是使用键盘快捷键(Windows中的Ctrl+V)还是上下文菜单,都会发生例外。我当然可以为每个TextField
添加一个try-catch块,但这会使代码变得混乱,我怎么知道只有在这种情况下才会抛出这个异常呢?
注意:此问题似乎不会影响TextArea
异常的全文:
Exception in thread "JavaFX Application Thread" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.AbstractStringBuilder.substring(Unknown Source)
at java.lang.StringBuilder.substring(Unknown Source)
at javafx.scene.control.TextField$TextFieldContent.get(Unknown Source)
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 javafx.scene.control.TextInputControl.replaceText(Unknown Source)
at javafx.scene.control.TextInputControl.replaceSelection(Unknown Source)
at javafx.scene.control.TextInputControl.paste(Unknown Source)
at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.paste(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$74(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.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$353(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$148(Unknown Source)
at java.lang.Thread.run(Unknown Source)
发布于 2016-03-15 20:59:49
这太难看了。您应该将此报告为错误。
你可以用一个TextFormatter
来过滤掉制表符(和换行符)来解决这个问题。您可能希望将制表符替换为,例如四个空格。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TextFieldBug extends Application {
@Override
public void start(Stage primaryStage) {
TextField tf = new TextField();
tf.setTextFormatter(new TextFormatter<String>((Change c) -> {
String text = c.getText();
int oldAnchor = c.getAnchor();
int oldCaretPos = c.getCaretPosition() ;
int initialLength = text.length();
text = text.replaceAll("\t", " ");
text = text.replaceAll("\n", "");
c.setText(text);
c.setAnchor(oldAnchor + text.length() - initialLength);
c.setCaretPosition(oldCaretPos + text.length() - initialLength);
return c ;
}));
primaryStage.setScene(new Scene(new StackPane(tf), 350, 120));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
发布于 2016-03-16 04:30:01
看起来是个窃听器。作为一种解决办法,您可以处理DefaultUncaughtEcxeptionHanlder
中的错误,这样应用程序就不会崩溃(参见例如..General Exception handling in JavaFX 8)
发布于 2018-10-15 02:01:47
我在javafx.scene.control.TextField
上遇到了同样的问题,所以我把它报告为一个错误:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8212102 / https://bugs.openjdk.java.net/browse/JDK-8212102。甲骨文的人说这是JDK 8u40中的一种回归。只要它没有被修复,James_D建议的变通方法就像一个魔咒一样工作。
https://stackoverflow.com/questions/36009368
复制相似问题