【问题标题】:Breaking JavaFX when Tab character is pasted into TextField将 Tab 字符粘贴到 TextField 时破坏 JavaFX
【发布时间】:2016-03-15 11:00:58
【问题描述】:

如果用户将制表符粘贴到 TextField 中,JavaFX 应用程序线程将抛出 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>

程序:

  1. 将制表符 (\t) 复制到剪贴板
  2. TextField 中输入一些内容
  3. 突出显示TextField 中的文本
  4. 粘贴剪贴板的内容以替换突出显示的文本

无论用户使用键盘快捷键(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)

【问题讨论】:

  • 您发布的代码对我们没有任何帮助,我们需要查看您正在操作 StringBuilder 的代码
  • @Xoce웃Пepeúpa 我不操纵StringBuilder;它是TextField 实现的内部。我发布的代码是一个可以重现结果的完整最小示例。
  • 你是对的。我只是在自己的应用程序中尝试过。我也遇到了同样的问题。

标签: java exception javafx textfield


【解决方案1】:

这很丑。您应该将此报告为错误。

您可以使用过滤掉制表符(和换行符)的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);
    }
}

【讨论】:

    【解决方案2】:

    似乎是一个错误。作为一种解决方法,您可以处理 DefaultUncaughtEcxeptionHanlder 中的错误,以使应用程序不会崩溃(参见例如 General Exception handling in JavaFX 8

    【讨论】:

      【解决方案3】:

      javafx.scene.control.TextField 遇到了同样的问题,因此我将其报告为错误:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8212102 / https://bugs.openjdk.java.net/browse/JDK-8212102。 Oracle 人说这是 JDK 8u40 的回归。只要不修复,James_D 建议的解决方法就像一个魅力。

      【讨论】:

        猜你喜欢
        • 2020-12-04
        • 1970-01-01
        • 2015-03-21
        • 1970-01-01
        • 1970-01-01
        • 2020-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多