﻿{"id":2282,"date":"2016-12-10T02:12:59","date_gmt":"2016-12-09T17:12:59","guid":{"rendered":"http:\/\/yucchi.jp\/blog\/?p=2282"},"modified":"2016-12-10T02:13:41","modified_gmt":"2016-12-09T17:13:41","slug":"hitinfo%e3%82%92%e5%b0%91%e3%81%97%e3%81%a0%e3%81%91","status":"publish","type":"post","link":"http:\/\/yucchi.jp\/blog\/?p=2282","title":{"rendered":"HitInfo\u3092\u5c11\u3057\u3060\u3051&hellip;"},"content":{"rendered":"<p>\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u306f\u3001<a href=\"http:\/\/qiita.com\/advent-calendar\/2016\/javafx\" target=\"_blank\">JavaFX Advent Calendar 2016<\/a> \u306e10\u65e5\u76ee\u3067\u3059\u3002<\/p>\n<p>\u6628\u65e5\u306f <a href=\"https:\/\/twitter.com\/nodamushi\" target=\"_blank\">@nodamushi<\/a> \u3055\u3093\u306e\u300c<a href=\"http:\/\/nodamushi.hatenablog.com\/entry\/2016\/12\/09\/015033\" target=\"_blank\">JavaFX9\u304c\u826f\u3044\u611f\u3058\u306b\u306a\u3063\u3066\u304d\u305f\u4ef6<\/a>\u300d\u3067\u3057\u305f\u3002<\/p>\n<p>\u660e\u65e5\u306f <a href=\"https:\/\/twitter.com\/skrb\" target=\"_blank\">@skrb<\/a> \u3055\u3093\u306e\u300c\u4f55\u304b\u66f8\u304d\u307e\u3059\u300d\u3067\u3059\u3002<\/p>\n<p>\u79c1\u306f\u82f1\u8a9e\u304c\u3088\u304f\u89e3\u3089\u306a\u3044\u306e\u30672015\u5e74\u306b\u3053\u3093\u306a\u3082\u306e\u3092\u4f5c\u308d\u3046\u3068\u3057\u307e\u3057\u305f\u3002(^_^;<\/p>\n<p>\u82f1\u6587\u30b5\u30a4\u30c8\u3092\u8aad\u307f\u8fbc\u3093\u3067\u30c6\u30ad\u30b9\u30c8\u5316\u3057\u3001\u82f1\u5358\u8a9e\u306e\u4e0a\u306b\u30de\u30a6\u30b9\u3092\u3042\u3066\u308b\u3068\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u3067\u65e5\u672c\u8a9e\u8a33\u3092\u8868\u793a\u3059\u308b\u3068\u3044\u3046\u5b89\u6613\u306a\u767a\u60f3\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/1.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"1\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"1\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/1_thumb.jpg\" width=\"722\" height=\"334\"><\/a><\/p>\n<p><a title=\"https:\/\/www.youtube.com\/watch?v=JfifsvUVeKE\" href=\"https:\/\/www.youtube.com\/watch?v=JfifsvUVeKE\">https:\/\/www.youtube.com\/watch?v=JfifsvUVeKE<\/a><\/p>\n<p>\u4f5c\u3063\u3066\u308b\u9014\u4e2d\u3067\u3044\u304f\u3064\u304b\u306e\u554f\u984c\u306b\u906d\u9047\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u305d\u306e\u4e2d\u3067 JavaFX \u3067\u306f Swing \u306e <\/p>\n<p>javax.\u200bswing.\u200btext.\u200bJTextComponent public int viewToModel(Point pt) <\/p>\n<p>javax.\u200bswing.\u200btext.\u200bJTextComponent public Rectangle modelToView(int pos) throws BadLocationException<\/p>\n<p>\u3053\u308c\u306b\u76f8\u5f53\u3059\u308b\u3082\u306e\u306f\u3042\u308b\u306e\u3060\u308d\u3046\u304b\uff1f\u3068\u3044\u3046\u7d20\u6734\u306a\u7591\u554f\u3067\u3059\u3002<\/p>\n<p>\u8abf\u3079\u3066\u307f\u305f\u3068\u3053\u308d com.\u200bsun.\u200bjavafx.\u200bscene.\u200btext public class HitInfo extends Object \u3092\u4f7f\u3048\u3070\u306a\u3093\u3068\u304b\u306a\u308a\u305d\u3046\u3067\u3059\u3002<\/p>\n<p>\u5b9f\u306f\u3001Rectangle modelToView(int pos) \u306f\u9762\u5012\u304f\u3055\u305d\u3046\u3060\u3063\u305f\u306e\u3067\u305d\u308c\u3092\u4f7f\u308f\u305a\u306b\u624b\u629c\u304d\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u3067\u59a5\u5354\u3057\u3066\u3044\u307e\u3057\u305f\u3002<\/p>\n<p>\u4e00\u5e74\u4ee5\u4e0a\u3053\u306e\u554f\u984c\u3092\u653e\u7f6e\u3057\u305f\u307e\u307e\uff08\u5fd8\u308c\u3066\u3044\u305f\u3068\u3082\u8a00\u3046\u30fb\u30fb\u30fb\uff09\u3060\u3063\u305f\u306e\u3067 <a href=\"http:\/\/qiita.com\/advent-calendar\/2016\/javafx\" target=\"_blank\">JavaFX Advent Calendar 2016<\/a> \u306e\u30cd\u30bf\u3068\u3057\u3066\u8abf\u3079\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u5c0f\u30cd\u30bf\u3067\u3059\u304c \u53c2\u8003\u8cc7\u6599\u306e\u5c11\u306a\u3044 JavaFX \u306a\u306e\u3067\u30e1\u30e2\u3068\u3057\u3066\u6b8b\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<p>\u3055\u3066\u3001\u3053\u3053\u304b\u3089\u5148\u306f\u4f55\u3082\u8003\u3048\u305a\u306b\u9069\u5f53\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u7d44\u3093\u3067\u3044\u3063\u305f\u79c1\u304c\u6b21\u3005\u3068\u554f\u984c\u306b\u3076\u3061\u5f53\u305f\u3063\u3066\u6ce3\u3044\u305f\u8a18\u9332\u3067\u3059\u3002<\/p>\n<p>BreakIterator \u3092\u4f7f\u3063\u305f\u7c21\u6613\u7684\u306a\u5f62\u614b\u7d20\u89e3\u6790\u306e\u8aac\u660e\u306f\u7701\u7565\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u307e\u3059\u3002<\/p>\n<p>\u30c6\u30ad\u30b9\u30c8\u30a8\u30ea\u30a2\u306b\u9069\u5f53\u306a\u82f1\u6587\u3092\u8868\u793a\u3057\u3066\u82f1\u5358\u8a9e\u4e0a\u306b\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\uff08\u30ad\u30e3\u30ec\u30c3\u30c8\uff09\u3092\u3082\u3063\u3066\u3044\u304f\u3068\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u3067 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304b\u3089\u53d6\u5f97\u3057\u305f\u30c7\u30fc\u30bf\u306a\u3069\u3092\u8868\u793a\u3055\u305b\u308b\u3068\u3044\u3046\u30b7\u30f3\u30d7\u30eb\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u4f5c\u3063\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<pre title=\"HitInfoWord.java\">package jp.yucchi.hitinfoword;\r\n\r\nimport com.sun.javafx.scene.control.skin.TextAreaSkin;\r\nimport com.sun.javafx.scene.text.HitInfo;\r\nimport java.io.PrintWriter;\r\nimport java.io.StringWriter;\r\nimport java.lang.reflect.Field;\r\nimport java.util.Optional;\r\nimport java.util.logging.Level;\r\nimport java.util.logging.Logger;\r\nimport javafx.animation.KeyFrame;\r\nimport javafx.animation.Timeline;\r\nimport javafx.application.Application;\r\nimport static javafx.application.Application.launch;\r\nimport javafx.application.Platform;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.control.Alert;\r\nimport javafx.scene.control.ButtonType;\r\nimport javafx.scene.control.TextArea;\r\nimport javafx.scene.control.Tooltip;\r\nimport javafx.scene.layout.StackPane;\r\nimport javafx.stage.Stage;\r\nimport javafx.stage.StageStyle;\r\nimport javafx.util.Duration;\r\nimport jp.yucchi.Dictionary4MorphologicalAnalysis.MorphologicalAnalysis;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class HitInfoWord extends Application {\r\n\r\n    private final MorphologicalAnalysis morphologicalAnalysis = new MorphologicalAnalysis();\r\n\r\n    private String word;\r\n\r\n    private final boolean debug = true;\r\n\r\n    \/\/ Tooltip Timer\r\n    private static final int TOOLTIP_ACTIVATION_TIME = 500;\r\n    private static final int TOOLTIP_HIDE_TIME = 10_000;\r\n\r\n    private static final String TEXT_DATA = \"Minimal Value Types\\n\"\r\n            + \"\\n\"\r\n            + \"The specific features of our minimum (but viable) support for value types can be summarized as follows:\\n\"\r\n            + \"A few value-capable classes (Int128, etc.) from which the VM may derive value types. \"\r\n            + \"These can be standard POJO class files.\\n\"\r\n            + \"Descriptor syntax (\u201cQ-types\u201d) for describing new value types in class-files.\\n\"\r\n            + \"Enhanced constants in the constant pool, to interoperate with these descriptors.\\n\"\r\n            + \"Three bytecode instructions (vload, etc.) for moving value types between JVM locals and stack.\\n\"\r\n            + \"Limited reflection for value types (similar to int.class).\\n\"\r\n            + \"Boxing and unboxing, to represent values (like primitives) in terms of Java\u2019s universal Object type.\\n\"\r\n            + \"Method handle factories to provide access to value operations (member access, etc.)\\n\"\r\n            + \"Standard Java source code, including generic classes and methods, \"\r\n            + \"will be able to refer to values only in their boxed form. \"\r\n            + \"However, both method handles and specially-generated bytecodes \"\r\n            + \"will be able to work with values in their native, unboxed form.\\n\"\r\n            + \"This work relates to the JVM, not to the language. Therefore non-goals include:\\n\"\r\n            + \"Syntax for defining or using value types directly from Java code.\\n\"\r\n            + \"Specialized generics in Java code which can store or process unboxed values (or primitives).\\n\"\r\n            + \"Library value types or evolved versions of value-based classes like java.util.Optional.\\n\"\r\n            + \"Access to value types from arbitrary modules. (Typically, value-capable classes will not be exported.)\\n\"\r\n            + \"Given the slogan \u201ccodes like a class, works like an int,\u201d \"\r\n            + \"which captures the overall vision for value types, this minimal set will deliver something more like \"\r\n            + \"\u201cworks like an int, if you can catch one\u201d.\\n\"\r\n            + \"By limiting the scope of this work, we believe useful experimentation can be enabled in a production \"\r\n            + \"JVM much earlier than if the entire value-type stack were delivered all at once.\\n\"\r\n            + \"The rest of this document goes into the proposed features in detail.\";\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n        int sceneWidth = 800;\r\n        int sceneHeight = 250;\r\n\r\n        StackPane root = new StackPane();\r\n\r\n        TextArea textArea = new TextArea();\r\n        textArea.setWrapText(true);\r\n        textArea.setEditable(false);\r\n        textArea.setStyle(\"-fx-text-fill: black;\" + \"-fx-font-weight: normal;\" + \"-fx-font-size: 24;\");\r\n        textArea.setText(TEXT_DATA);\r\n\r\n        final Tooltip tooltip = new Tooltip();\r\n        myTooltipTimer(tooltip);\r\n\r\n        try {\r\n            Optional&lt;String&gt; text = Optional.ofNullable(textArea.getText());\r\n            morphologicalAnalysis.setText(text.orElseThrow((() -&gt; new Exception())));\r\n        } catch (Exception ex) {\r\n            exceptionOccured(ex);\r\n        }\r\n\r\n        textArea.layoutBoundsProperty().addListener(e -&gt; {\r\n            textArea.setScrollTop(0);\r\n        });\r\n\r\n        textArea.scrollTopProperty().addListener(e -&gt; {\r\n            Tooltip.uninstall(textArea, tooltip);\r\n        });\r\n\r\n        textArea.setOnMouseMoved(e -&gt; {\r\n            TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n            HitInfo hitInfo = textAreaSkin.getIndex(e.getX(),\r\n                    e.getY() + textArea.scrollTopProperty().getValue());\r\n\r\n            \/\/ \u6587\u5b57\u30c7\u30fc\u30bf\u53d6\u5f97\r\n            word = null;\r\n            Optional.ofNullable(morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()))\r\n                    .ifPresent(morpheme -&gt; {\r\n                        word = morpheme.word;\r\n                    });\r\n\r\n            \/\/ TextArea \u30b3\u30f3\u30c6\u30f3\u30c4\u5185\u3067\u6587\u5b57\u4e0a\u306b\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u3042\u308b\u5834\u5408\u306b Tooltip\u3092\u8868\u793a\r\n            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null) {\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n\r\n            tooltip.setText(\"X: \" + e.getX() + \"\\n\"\r\n                    + \"Y: \" + (e.getY() + textArea.scrollTopProperty().getValue()) + \"\\n\"\r\n                    + \"getCharIndex: \" + hitInfo.getCharIndex() + \"\\n\"\r\n                    + \"getInsertionIndex: \" + hitInfo.getInsertionIndex() + \"\\n\"\r\n                    + \"isLeading: \" + hitInfo.isLeading() + \"\\n\"\r\n                    + word);\r\n\r\n            if (debug) {\r\n                System.out.println(\"X: \" + e.getX() + \"\\n\"\r\n                        + \"Y: \" + (e.getY() + textArea.scrollTopProperty().getValue()) + \"\\n\"\r\n                        + \"getCharIndex: \" + hitInfo.getCharIndex() + \"\\n\"\r\n                        + \"getInsertionIndex: \" + hitInfo.getInsertionIndex() + \"\\n\"\r\n                        + \"isLeading: \" + hitInfo.isLeading() + \"\\n\"\r\n                        + word + \"\\n\");\r\n            }\r\n\r\n        });\r\n\r\n        root.getChildren().add(textArea);\r\n        Scene scene = new Scene(root, sceneWidth, sceneHeight);\r\n\r\n        primaryStage.setTitle(this.getClass().getSimpleName());\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n    \/\/ TooltipTimer \u5909\u66f4\r\n    private void myTooltipTimer(Tooltip tooltip) {\r\n        try {\r\n            Field fieldBehavior = tooltip.getClass().getDeclaredField(\"BEHAVIOR\");\r\n            fieldBehavior.setAccessible(true);\r\n            Object objBehavior = fieldBehavior.get(tooltip);\r\n\r\n            Field activationTimer = objBehavior.getClass().getDeclaredField(\"activationTimer\");\r\n            activationTimer.setAccessible(true);\r\n\r\n            Timeline activationTimeline = (Timeline) activationTimer.get(objBehavior);\r\n            activationTimeline.getKeyFrames().clear();\r\n            activationTimeline.getKeyFrames().add(new KeyFrame(new Duration(TOOLTIP_ACTIVATION_TIME)));\r\n\r\n            Field hideTimer = objBehavior.getClass().getDeclaredField(\"hideTimer\");\r\n            hideTimer.setAccessible(true);\r\n\r\n            Timeline hideTimeline = (Timeline) hideTimer.get(objBehavior);\r\n            hideTimeline.getKeyFrames().clear();\r\n            hideTimeline.getKeyFrames().add(new KeyFrame(new Duration(TOOLTIP_HIDE_TIME)));\r\n        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {\r\n            Logger.getLogger(HitInfoWord.class.getName()).log(Level.SEVERE, null, ex);\r\n            exceptionOccured(ex);\r\n        }\r\n    }\r\n\r\n    private void exceptionOccured(Exception ex) {\r\n        Alert alert = new Alert(Alert.AlertType.ERROR);\r\n\r\n        StringWriter sw = new StringWriter();\r\n        PrintWriter pw = new PrintWriter(sw);\r\n        ex.printStackTrace(pw);\r\n        pw.flush();\r\n        String stackTrace = sw.toString();\r\n\r\n        TextArea textArea = new TextArea(stackTrace);\r\n        textArea.setEditable(false);\r\n        alert.getDialogPane().setExpandableContent(textArea);\r\n        alert.initStyle(StageStyle.TRANSPARENT);\r\n\/\/            alert.setTitle(\"ERROR\");\r\n        alert.setHeaderText(\"Error!\\n\" + ex.getClass().getSimpleName());\r\n        alert.setContentText(\"Exit the application.\");\r\n        alert.showAndWait()\r\n                .filter(response -&gt; response == ButtonType.OK)\r\n                .ifPresent(response -&gt; {\r\n                    Platform.exit();\r\n                    System.exit(0);\r\n                });\r\n    }\r\n\r\n}\r\n\r\n<\/pre>\n<pre title=\"MorphologicalAnalysis.java\">package jp.yucchi.Dictionary4MorphologicalAnalysis;\r\n\r\nimport java.text.BreakIterator;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\nimport java.util.Locale;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class MorphologicalAnalysis {\r\n\r\n    private final List&lt;Morpheme&gt; morphemeList = new ArrayList&lt;&gt;();\r\n    private Morpheme morpheme;\r\n\r\n    public void setText(String text) {\r\n        morphemeList.clear();\r\n        BreakIterator boundary = BreakIterator.getWordInstance(Locale.ENGLISH);\r\n        boundary.setText(text);\r\n        int start = boundary.first();\r\n        int end = boundary.next();\r\n\r\n        while (end != BreakIterator.DONE) {\r\n            String word = text.substring(start, end);\r\n            if (Character.isLetterOrDigit(word.charAt(0))) {\r\n                morphemeList.add(new Morpheme(start, end, word));\r\n            }\r\n            start = end;\r\n            end = boundary.next();\r\n        }\r\n    }\r\n\r\n    public Morpheme getMorpheme(int charIndex) {\r\n        morpheme = null;\r\n        morphemeList.stream()\r\n                .filter(e -&gt; e.range(charIndex))\r\n                .findFirst()\r\n                .ifPresent(e -&gt; {\r\n                    morpheme = e;\r\n                });\r\n\r\n        return morpheme;\r\n    }\r\n\r\n}\r\n\r\n<\/pre>\n<pre title=\"Morpheme.java\">package jp.yucchi.Dictionary4MorphologicalAnalysis;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class Morpheme {\r\n\r\n    public int start;\r\n    public int end;\r\n    public String word;\r\n\r\n    public Morpheme(int start, int end, String word) {\r\n        this.start = start;\r\n        this.end = end;\r\n        this.word = word;\r\n    }\r\n\r\n    boolean range(int charIndex) {\r\n        return start &lt;= charIndex &amp;&amp; charIndex &lt; end;\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3057\u3066 Minimal \u3068\u3044\u3046\u82f1\u5358\u8a9e\u306e M \u306e\u4e2d\u592e\u3088\u308a\u5de6\u306e\u4f4d\u7f6e\u306b\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u3092\u3082\u3063\u3066\u3044\u304f\u3068\u6b21\u306e\u3088\u3046\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/2.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"2\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"2\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/2_thumb.jpg\" width=\"236\" height=\"244\"><\/a><\/p>\n<p>\u4e2d\u592e\u3088\u308a\u53f3\u306e\u4f4d\u7f6e\u306b\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u3092\u3082\u3063\u3066\u3044\u304f\u3068\u6b21\u306e\u3088\u3046\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/3.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"3\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"3\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/3_thumb.jpg\" width=\"244\" height=\"243\"><\/a><\/p>\n<p>\u305d\u308c\u3067\u306f\u3053\u308c\u3089\u304c\u3069\u3046\u3044\u3063\u305f\u30c7\u30fc\u30bf\u306a\u306e\u304b\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u307f\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n<p>X, Y \u306f TextArea \u5185\u306e\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u306e\u5ea7\u6a19\u30c7\u30fc\u30bf\u3067\u3059\u3002<\/p>\n<p>\u3053\u308c\u3089\u306e\u5ea7\u6a19\u30c7\u30fc\u30bf\u306f HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3059\u308b\u305f\u3081\u306b\u4f7f\u3044\u307e\u3059\u3002<\/p>\n<p>HitInfo \u30af\u30e9\u30b9\u306f\u30c6\u30ad\u30b9\u30c8\u30ce\u30fc\u30c9\u306e\u30d2\u30c3\u30c8\u60c5\u5831\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u306b\u4f7f\u308f\u308c\u307e\u3059\u3002<\/p>\n<p>TextArea \u306e HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u306b\u306f <\/p>\n<p>com.\u200bsun.\u200bjavafx.\u200bscene.\u200bcontrol.\u200bskin public class TextAreaSkin extends TextInputControlSkin&lt;TextArea,TextAreaBehavior&gt;<\/p>\n<p>\u3092\u53d6\u5f97\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>javafx.\u200bscene.\u200bcontrol.\u200bControl public final Skin&lt;?&gt; getSkin() \u30e1\u30bd\u30c3\u30c9\u3067 TextArea \u306e\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u7528\u306e Skin \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002<\/p>\n<p>\u305d\u3057\u3066\u3001com.\u200bsun.\u200bjavafx.\u200bscene.\u200bcontrol.\u200bskin.\u200bTextAreaSkin public HitInfo getIndex(double x, double y) \u30e1\u30bd\u30c3\u30c9\u306b\u3088\u308a (\u5f15\u6570\u306f TextArea \u5185\u306e\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u306e\u5ea7\u6a19\u30c7\u30fc\u30bf\u3067\u3059)<\/p>\n<p>\u5f15\u6570\u306e\u5ea7\u6a19\u30c7\u30fc\u30bf\u306b\u57fa\u3065\u3044\u3066\u30d2\u30c3\u30c8\u30c6\u30b9\u30c8\u3092\u5b9f\u884c\u3057\u3001\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u30de\u30c3\u30d4\u30f3\u30b0\u3057\u3066 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002<\/p>\n<p>\u3053\u3053\u307e\u3067\u306e\u30b3\u30fc\u30c9\u3092\u78ba\u8a8d\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>TextArea \u5185\u3067\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u306e\u79fb\u52d5\u304c\u691c\u51fa\u3055\u308c\u305f\u3068\u304d\u306b\u5b9f\u884c\u3055\u308c\u308b\u3088\u3046\u306b\u3057\u3066\u307e\u3059\u3002<\/p>\n<pre title=\"HitInfoWord.java\">        textArea.setOnMouseMoved(e -&gt; {\r\n            TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n            HitInfo hitInfo = textAreaSkin.getIndex(e.getX(),\r\n                    e.getY() + textArea.scrollTopProperty().getValue());\r\n\r\n<\/pre>\n<p>\u3053\u308c\u3067 HitInfo \u30af\u30e9\u30b9\u3092\u4f7f\u3046\u6e96\u5099\u304c\u3067\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u3067\u306f HitInfo \u30af\u30e9\u30b9\u3067\u306f\u3069\u3046\u3044\u3063\u305f\u3053\u3068\u304c\u3067\u304d\u308b\u306e\u304b\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n<p>HitInfo \u30af\u30e9\u30b9\u306b\u306f\u4e0b\u8a18\u306e\u30e1\u30bd\u30c3\u30c9\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p><font color=\"#333333\">public int getCharIndex()<\/font><\/p>\n<p><font color=\"#333333\">public boolean isLeading()<\/font><\/p>\n<p><font color=\"#333333\">public int getInsertionIndex()<\/font><\/p>\n<p><font color=\"#333333\">public String toString()<\/font><\/p>\n<p>\u3053\u308c\u3089\uff14\u500b\u306e\u30e1\u30bd\u30c3\u30c9\u306e\u3046\u3061 public String toString() \u30e1\u30bd\u30c3\u30c9\u4ee5\u5916\u306e\uff13\u500b\u306e\u30e1\u30bd\u30c3\u30c9\u3092\u8abf\u3079\u3066\u307f\u307e\u3059\u3002<\/p>\n<p><font color=\"#333333\">public int getCharIndex()<\/font><\/p>\n<p>\u3053\u308c\u306f HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u53c2\u7167\u3057\u3066\u3044\u308b\u6587\u5b57\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#333333\">public int getInsertionIndex()<\/font><\/p>\n<p>\u633f\u5165\u4f4d\u7f6e\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002<\/p>\n<p><font color=\"#333333\">public boolean isLeading()<\/font><\/p>\n<p>API \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306b\u306f\u4e0b\u8a18\u306e\u3088\u3046\u306b\u8a18\u8ff0\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p><font color=\"#333333\">Indicates whether the hit is on the leading edge of the character. If it is false, it represents the trailing edge.<\/font><\/p>\n<p><a name=\"getInsertionIndex--\"><\/a><\/p>\n<p>\u5b9f\u969b\u306b\u52d5\u4f5c\u3092\u78ba\u8a8d\u3057\u305f\u3068\u3053\u308d\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u304c\u6587\u5b57\u4e0a\u306e\u5de6\u5074\u304b\u53f3\u5074\u306b\u30d2\u30c3\u30c8\u3057\u3066\u3044\u308b\u304b\u5224\u5b9a\u3057\u3066\u3044\u308b\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u5de6\u5074\u3060\u3063\u305f\u3089 true\u3001\u53f3\u5074\u3060\u3063\u305f\u3089 false \u3092\u8fd4\u3057\u307e\u3059\u3002<\/p>\n<p>\u3053\u306e\u30e1\u30bd\u30c3\u30c9\u3092\u5229\u7528\u3057\u3066 public int getInsertionIndex() \u30e1\u30bd\u30c3\u30c9\u306f\u633f\u5165\u4f4d\u7f6e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u8fd4\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<pre title=\"HitInfo.java\">    \/**\r\n     * Returns the index of the insertion position.\r\n     *\/\r\n    public int getInsertionIndex() {\r\n        return leading ? charIndex : charIndex + 1;\r\n    }\r\n<\/pre>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u306f Tooltip \u306b\u3053\u308c\u3089\u306e\u30e1\u30bd\u30c3\u30c9\u306b\u3088\u308a\u53d6\u5f97\u3057\u305f\u30c7\u30fc\u30bf\u3092\u8868\u793a\u3055\u305b\u308b\u3088\u3046\u306b\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<pre title=\"HitInfoWord.java\">            tooltip.setText(\"X: \" + e.getX() + \"\\n\"\r\n                    + \"Y: \" + (e.getY() + textArea.scrollTopProperty().getValue()) + \"\\n\"\r\n                    + \"getCharIndex: \" + hitInfo.getCharIndex() + \"\\n\"\r\n                    + \"getInsertionIndex: \" + hitInfo.getInsertionIndex() + \"\\n\"\r\n                    + \"isLeading: \" + hitInfo.isLeading() + \"\\n\"\r\n                    + word);\r\n<\/pre>\n<p>\u6700\u5f8c\u306e\u884c\u306b\u3042\u308b word \u306f\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u4e0a\u306e\u5358\u8a9e\u3092 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u5229\u7528\u3057\u3066\u53d6\u5f97\u3057\u305f\u3082\u306e\u3067\u3059\u3002<\/p>\n<pre title=\"HitInfoWord.java\">            \/\/ \u6587\u5b57\u30c7\u30fc\u30bf\u53d6\u5f97\r\n            word = null;\r\n            Optional.ofNullable(morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()))\r\n                    .ifPresent(morpheme -&gt; {\r\n                        word = morpheme.word;\r\n                    });\r\n<\/pre>\n<p>\u3055\u3066\u3001Tooltip \u306f\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u304c\u6587\u5b57\u4e0a\u306b\u3042\u308b\u5834\u5408\u3060\u3051\u8868\u793a\u3055\u305b\u305f\u3044\u306e\u3067\u5358\u7d14\u306b\u6b21\u306e\u3088\u3046\u306a\u6761\u4ef6\u5f0f\u3092\u5b9f\u88c5\u3057\u307e\u3057\u305f\u3002<\/p>\n<pre title=\"HitInfoWord.java\">            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null) {\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n<\/pre>\n<p>\u3068\u3053\u308d\u304c\u3053\u3093\u306a\u5358\u7d14\u306b\u671f\u5f85\u901a\u308a\u306e\u7d50\u679c\u306f\u5f97\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/4.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"4\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"4\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/4_thumb.jpg\" width=\"644\" height=\"206\"><\/a><\/p>\n<p><font color=\"#ff0000\" size=\"3\"><strong>\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u304c\u6587\u5b57\u4e0a\u306b\u306a\u3044\u3068\u3053\u308d\u3067\u3082 Tooltip \u304c\u8868\u793a\u3055\u308c\u3066\u3057\u307e\u3044\u307e\u3059\u3002\uff08\u00d7_\u00d7\uff09<\/strong><\/font><\/p>\n<p>\u3068\u308a\u3042\u3048\u305a\u306e\u5bfe\u7b56\u3068\u3057\u3066\u4e0b\u8a18\u306e\u3088\u3046\u306b\u4fee\u6b63\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>public int getInsertionIndex() \u3092\u5229\u7528\u3057\u3066\u6700\u5f8c\u306e\u6587\u5b57\u306e\u633f\u5165\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\uff08\u6700\u5f8c\u306e\u6587\u5b57\u306e\u6b21\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\uff09Morpheme \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u5b58\u5728\u3059\u308b\u304b\u306e\u5224\u5b9a\u3092\u8ffd\u52a0\u3057\u307e\u3057\u305f\u3002<\/p>\n<pre title=\"HitInfoWord.java\">            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null\r\n                    &amp;&amp; morphologicalAnalysis.getMorpheme(hitInfo.getInsertionIndex()) != null) {\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n<\/pre>\n<p>\u5f53\u7136\u3053\u306e\u30b3\u30fc\u30c9\u3067\u306f\u6587\u5b57\u306e\u6700\u5f8c\u306e\u53f3\u534a\u5206\u4e0a\u306b\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u304c\u30d2\u30c3\u30c8\u3057\u3066\u3044\u3066\u3082 Tooltip \u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093\u3002<\/p>\n<p>\u3053\u306e\u4e0d\u5177\u5408\u3082\u3059\u3050\u306b\u89e3\u6c7a\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u306a\u3044\u306e\u3067\u3059\u304c\u4ed6\u306b\u3082\u554f\u984c\u304c\u3042\u308b\u306e\u3067\u3068\u308a\u3042\u3048\u305a\u5f8c\u56de\u3057\u3068\u3057\u307e\u3059\u3002<\/p>\n<p>\u6b21\u306b\u89e3\u6c7a\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u306a\u3044\u554f\u984c\u306f\u4e0b\u56f3\u306e\u3088\u3046\u306a\u3082\u306e\u3067\u3059\u3002<\/p>\n<p><font color=\"#ff0000\" size=\"3\"><strong>\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u304c\u53f3\u306e\u4f59\u767d\u90e8\u5206\u3001\u4e0a\u306e\u4f59\u767d\u90e8\u5206\u306b\u3042\u3063\u3066\u3082 Tooltip \u304c\u8868\u793a\u3055\u308c\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/strong><\/font><\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/5.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"5\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"5\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/5_thumb.jpg\" width=\"205\" height=\"244\"><\/a>&nbsp;<a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/6.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"6\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"6\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/6_thumb.jpg\" width=\"244\" height=\"209\"><\/a><\/p>\n<p>\u3053\u308c\u3089\u4f59\u767d\u90e8\u5206\u3067 Tooltip \u3092\u8868\u793a\u3055\u305b\u306a\u3044\u305f\u3081\u306b\u306f TextArea \u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4f59\u767d\u306e\u5024\u3092\u53d6\u5f97\u3059\u308b\u3053\u3068\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u306f\u4ed5\u69d8\u3060\u3068\u3042\u304d\u3089\u3081\u3088\u3046\u3068\u3057\u305f\u3051\u3069\u30fb\u30fb\u30fb\u3000\u3069\u3046\u3082\u3053\u308c\u3067\u306f\u7720\u308c\u306a\u304f\u306a\u308a\u305d\u3046\u306a\u306e\u3067\u5996\u3057\u3044 TextAreaSkin \u30af\u30e9\u30b9\u306e\u30bd\u30fc\u30b9\u3092\u8997\u3044\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u305f\u3076\u3093\u3053\u308c\u3060\u3068\u601d\u3046\u306e\u3067\u4f7f\u3063\u3066\u307f\u308b\u3053\u3068\u306b\u3057\u307e\u3059\u3002<\/p>\n<pre title=\"TextAreaSkin.java\">    private double getTextTranslateX() {\r\n        return contentView.snappedLeftInset();\r\n    }\r\n\r\n    private double getTextTranslateY() {\r\n        return contentView.snappedTopInset();\r\n    }\r\n\r\n<\/pre>\n<p>private \u30e1\u30bd\u30c3\u30c9\u306a\u306e\u3067\u30ea\u30d5\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u5229\u7528\u3057\u3066\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002<\/p>\n<pre title=\"HitInfoWord.java\">        \r\n\t\/\/ TextArea Default Inset \u53d6\u5f97 \u3053\u306e\u4e8c\u3064\u306e\u5909\u6570\u306f\u30d5\u30a3\u30fc\u30eb\u30c9\u3067\u3059\u3002\r\n\tleftInset = getLeftInset(textArea);\r\n\ttopInset = getTopInset(textArea);\r\n\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\r\n    private double getLeftInset(TextArea textArea) {\r\n        TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n        Method method = null;\r\n        try {\r\n            method = textAreaSkin.getClass().getDeclaredMethod(\"getTextTranslateX\");\r\n            method.setAccessible(true);\r\n        } catch (NoSuchMethodException | SecurityException ex) {\r\n            Logger.getLogger(HitInfoWord.class.getName()).log(Level.SEVERE, null, ex);\r\n            exceptionOccured(ex);\r\n        }\r\n        double left = 0;\r\n        try {\r\n            left = (double) method.invoke(textAreaSkin);\r\n        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {\r\n            Logger.getLogger(HitInfoWord.class.getName()).log(Level.SEVERE, null, ex);\r\n            exceptionOccured(ex);\r\n        }\r\n\r\n        return left;\r\n    }\r\n\r\n<\/pre>\n<p>private double getTextTranslateY() \u30e1\u30bd\u30c3\u30c9\u306e\u30c7\u30fc\u30bf\u306e\u53d6\u5f97\u306f\u540c\u69d8\u306b\u3057\u307e\u3059\u306e\u3067\u30b3\u30fc\u30c9\u306f\u7701\u7565\u3055\u305b\u3066\u3044\u305f\u3060\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u3053\u308c\u3067\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4f59\u767d\u30c7\u30fc\u30bf\u306f\u53d6\u5f97\u3067\u304d\u308b\u306e\u3067 Tooltip \u306e\u8868\u793a\u3092\u5236\u5fa1\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u30b9\u30af\u30ed\u30fc\u30eb\u3055\u305b\u3066\u3057\u307e\u3048\u3070\u4e0a\u90e8\u306e\u4f59\u767d\u306f\u96a0\u308c\u3066\u3057\u307e\u3046\u306e\u3067\u3059\u304c\u6587\u5b57\u304c\u4e2d\u9014\u534a\u7aef\u306b\u898b\u5207\u308c\u3066\u3044\u308b\u306e\u306b Tooltip \u3092\u8868\u793a\u3055\u305b\u308b\u5fc5\u8981\u306f\u306a\u3044\u306e\u3067\u5e38\u306b\u4e0a\u4e0b\u5de6\u53f3\u306e\u4f59\u767d\u5206\u3092\u8868\u793a\u3055\u305b\u306a\u3044\u3088\u3046\u306b\u3057\u307e\u3057\u305f\u3002<\/p>\n<pre title=\"HitInfoWord.java\">            \/\/ TextArea \u30b3\u30f3\u30c6\u30f3\u30c4\u5185\u3067\u6587\u5b57\u4e0a\u306b\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u3042\u308b\u5834\u5408\u306b Tooltip\u3092\u8868\u793a\r\n            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null\r\n                    &amp;&amp; morphologicalAnalysis.getMorpheme(hitInfo.getInsertionIndex()) != null\r\n                    &amp;&amp; e.getX() &gt; leftInset\r\n                    &amp;&amp; e.getY() &gt; topInset\r\n                    &amp;&amp; e.getX() &lt; textArea.getWidth() - leftInset\r\n                    &amp;&amp; e.getY() &lt; textArea.getHeight() - topInset) {\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n<\/pre>\n<p>\u4e00\u5fdc\u3053\u308c\u3067\u3082\u52d5\u304f\u306e\u3067\u3059\u304c\u3082\u3063\u3068\u30b9\u30de\u30fc\u30c8\u306a\u65b9\u6cd5\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>javafx.\u200bscene.\u200bParent public Node lookup(String selector) \u30e1\u30bd\u30c3\u30c9\u306b\u3066\u5f15\u6570\u3067\u6307\u5b9a\u3057\u305f CSS \u30bb\u30ec\u30af\u30bf\u306b\u57fa\u3065\u3044\u3066\u30ce\u30fc\u30c9\u3092\u691c\u7d22\u3057\u307e\u3059\u3002<\/p>\n<p>\u305d\u3057\u3066\u8fd4\u3055\u308c\u305f\u30ce\u30fc\u30c9\u306e\u30ec\u30a4\u30a2\u30a6\u30c8\u60c5\u5831\u3092\u53d6\u5f97\u3059\u308c\u3070\u3044\u3044\u3060\u3051\u3067\u3059\u3002<\/p>\n<pre title=\"HitInfoWord.java\">        Text textNode = (Text) textArea.lookup(\".text\");\r\n        \/\/ TextArea Default Inset \u53d6\u5f97\r\n        leftInset = textNode.getLayoutX();\r\n        topInset = textNode.getLayoutY();\r\n<\/pre>\n<p>\u3053\u3061\u3089\u306e\u307b\u3046\u304c\u7c21\u5358\u3067\u3059\u306d\uff01<\/p>\n<p>\u3055\u3066\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4f59\u767d\u306e\u5bfe\u51e6\u306f\u3053\u308c\u3067\u3044\u3044\u306e\u3067\u3059\u304c\u3001<\/p>\n<p>textArea.setPadding(new Insets(50, 50, 50, 50)); \/\/(top\/right\/bottom\/left)<\/p>\n<p>\u306e\u3088\u3046\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u4e0a\u3067\u8a2d\u5b9a\u3059\u308c\u3070\u3069\u3046\u306a\u308b\u3067\u3057\u3087\u3046\u304b\u3002<\/p>\n<p>\u3055\u3063\u305d\u304f\u8a66\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/7.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"7\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"7\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/7_thumb.jpg\" width=\"244\" height=\"225\"><\/a><\/p>\n<p><font color=\"#ff0000\" size=\"3\"><strong>\u306a\u3093\u3058\u3083\u3001\u3053\u308a\u3083\uff01<\/strong><\/font><\/p>\n<p>\u30c6\u30ad\u30b9\u30c8\u304c\u30d1\u30c7\u30a3\u30f3\u30b0\u306b\u3088\u308a\u30ec\u30a4\u30a2\u30a6\u30c8\u5909\u66f4\u3055\u308c\u3066\u3044\u308b\u306e\u3067\u5ea7\u6a19\u30c7\u30fc\u30bf\u3068\u30b3\u30f3\u30c6\u30f3\u30c4\u3068\u306e\u30de\u30c3\u30d4\u30f3\u30b0\u304c\u72c2\u3063\u3066\u3057\u307e\u3063\u3066\u307e\u3059\u3002<\/p>\n<p>\u305d\u3053\u3067 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u751f\u6210\u30b3\u30fc\u30c9\u3001Tooltip \u306e\u8868\u793a\u5236\u5fa1\u3092\u30d1\u30c7\u30a3\u30f3\u30b0\u306b\u3088\u3063\u3066\u305a\u308c\u3066\u3057\u307e\u3046\u5206\u306e\u88dc\u6b63\u3092\u8003\u616e\u3057\u6b21\u306e\u3088\u3046\u306b\u5909\u66f4\u3057\u307e\u3057\u305f\u3002<\/p>\n<pre title=\"HitInfoWord.java\">        textArea.setOnMouseMoved(e -&gt; {\r\n            TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n            HitInfo hitInfo = textAreaSkin.getIndex(e.getX() - textArea.getPadding().getLeft(),\r\n                    e.getY() + textArea.scrollTopProperty().getValue() - textArea.getPadding().getTop());\r\n<\/pre>\n<pre title=\"HitInfoWord.java\">            \/\/ TextArea \u30b3\u30f3\u30c6\u30f3\u30c4\u5185\u3067\u6587\u5b57\u4e0a\u306b\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u3042\u308b\u5834\u5408\u306b Tooltip\u3092\u8868\u793a\r\n            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null\r\n                    &amp;&amp; morphologicalAnalysis.getMorpheme(hitInfo.getInsertionIndex()) != null\r\n                    &amp;&amp; e.getX() &gt; textArea.getPadding().getLeft() + leftInset\r\n                    &amp;&amp; e.getY() &gt; textArea.getPadding().getTop() + topInset\r\n                    &amp;&amp; e.getX() &lt; textArea.getWidth() - textArea.getPadding().getRight() - leftInset\r\n                    &amp;&amp; e.getY() &lt; textArea.getHeight() - textArea.getPadding().getBottom() - topInset) {\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n<\/pre>\n<p>\u3053\u308c\u3067 OK !<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/8.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"8\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"8\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/8_thumb.jpg\" width=\"244\" height=\"237\"><\/a><\/p>\n<p>\u3053\u3093\u306a\u30b7\u30f3\u30d7\u30eb\u306a\u3053\u3068\u3092\u3055\u305b\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u3060\u3051\u306a\u306e\u306b\u4e00\u7b4b\u7e04\u3067\u306f\u3044\u304b\u306a\u3044\u3067\u3059\u306d\u3002<\/p>\n<p>\u3053\u3053\u3067\u3055\u3089\u306b\u7591\u554f\u304c\u6d6e\u4e0a\u3057\u3066\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u30c6\u30ad\u30b9\u30c8\u3092\u4e2d\u592e\u8868\u793a\u3055\u305b\u305f\u3089\u3069\u3046\u306a\u308b\u306e\uff1f<\/p>\n<p>\u4e0b\u8a18\u306e\u3088\u3046\u306a CSS \u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<pre title=\"myCSS.css\">.text-area *.text {\r\n    -fx-text-alignment: center;\r\n}\r\n<\/pre>\n<p><font color=\"#ff0000\" size=\"3\"><strong>\u3044\u3084\u306a\u4e88\u611f\u7684\u4e2d\u3067\u3059\u3002<\/strong><\/font><\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/9.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"9\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"9\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/9_thumb.jpg\" width=\"244\" height=\"159\"><\/a><\/p>\n<p>\u5de6\u306e\u4f59\u767d\u90e8\u5206\u3067 Tooltip \u304c\u8868\u793a\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u30c6\u30ad\u30b9\u30c8\u304c\u4e2d\u592e\u8868\u793a\u306b\u30ec\u30a4\u30a2\u30a6\u30c8\u5909\u66f4\u3055\u308c\u3066\u3044\u308b\u306e\u306b\u305d\u308c\u304c\u53cd\u6620\u3055\u308c\u305f\u7d50\u679c\u3068\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002<\/p>\n<p>\u3053\u306e\u554f\u984c\u3092\u89e3\u6c7a\u3059\u308b\u306b\u306f JavaFX \u3067 javax.\u200bswing.\u200btext.\u200bJTextComponent public Rectangle modelToView(int pos) throws BadLocationException \u306b\u76f8\u5f53\u3059\u308b\u6a5f\u80fd\u304c\u5fc5\u9808\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u6587\u5b57\u4e0a\u306b\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb\u304c\u6709\u308b\u304b\u7121\u3044\u304b\u306e\u5224\u5b9a\u304c\u3069\u3046\u3057\u3066\u3082\u5fc5\u8981\u3068\u306a\u308b\u304b\u3089\u3067\u3059\u3002<\/p>\n<p>\u3053\u308c\u304c\u53ef\u80fd\u3068\u306a\u308c\u3070\u3053\u308c\u307e\u3067\u8aa4\u9b54\u5316\u3057\u3066\u3044\u305f\u5168\u3066\u306e\u554f\u984c\u304c\u89e3\u6c7a\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u300c\u3069\u3046\u3057\u305f\u3082\u3093\u3058\u3083\u308d\u306e\u3046\u300d\u3068NHK\u9023\u7d9a\u30c6\u30ec\u30d3\u5c0f\u8aac\u300c\u3068\u3068\u59c9\u3061\u3083\u3093\u300d\u306e\u3088\u3046\u306b\u8003\u3048\u8fbc\u307f\u307e\u3057\u305f\u304c\u7b54\u3048\u306f\u7c21\u5358\u306b\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002<\/p>\n<p>TextArea \u306b\u306f\u30cf\u30a4\u30e9\u30a4\u30c8\u8868\u793a\u306e\u6a5f\u80fd\u304c\u3042\u308b\u304b\u3089\u7d76\u5bfe Rectangle modelToView(int pos) \u30e1\u30bd\u30c3\u30c9\u3068\u540c\u3058\u3088\u3046\u306a\u6a5f\u80fd\u304c\u5099\u308f\u3063\u3066\u3044\u308b\u306f\u305a\u3060\u3002<\/p>\n<p>TextArea \u306e\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u95a2\u4fc2\u3068\u8a00\u3048\u3070\u3001TextAreaSkin \u30af\u30e9\u30b9\u3067\u3059\u3088\u306d\u3002<\/p>\n<p>\u3042\u308a\u307e\u3057\u305f\uff01(^_^)<\/p>\n<pre title=\"TextAreaSkin.java\">    @Override\r\n    public Rectangle2D getCharacterBounds(int index) {\r\n        TextArea textArea = getSkinnable();\r\n\r\n        int paragraphIndex = paragraphNodes.getChildren().size();\r\n        int paragraphOffset = textArea.getLength() + 1;\r\n\r\n        Text paragraphNode = null;\r\n        do {\r\n            paragraphNode = (Text)paragraphNodes.getChildren().get(--paragraphIndex);\r\n            paragraphOffset -= paragraphNode.getText().length() + 1;\r\n        } while (index &lt; paragraphOffset);\r\n\r\n        int characterIndex = index - paragraphOffset;\r\n        boolean terminator = false;\r\n\r\n        if (characterIndex == paragraphNode.getText().length()) {\r\n            characterIndex--;\r\n            terminator = true;\r\n        }\r\n\r\n        characterBoundingPath.getElements().clear();\r\n        characterBoundingPath.getElements().addAll(paragraphNode.impl_getRangeShape(characterIndex, characterIndex + 1));\r\n        characterBoundingPath.setLayoutX(paragraphNode.getLayoutX());\r\n        characterBoundingPath.setLayoutY(paragraphNode.getLayoutY());\r\n\r\n        Bounds bounds = characterBoundingPath.getBoundsInLocal();\r\n\r\n        double x = bounds.getMinX() + paragraphNode.getLayoutX() - textArea.getScrollLeft();\r\n        double y = bounds.getMinY() + paragraphNode.getLayoutY() - textArea.getScrollTop();\r\n\r\n        \/\/ Sometimes the bounds is empty, in which case we must ignore the width\/height\r\n        double width = bounds.isEmpty() ? 0 : bounds.getWidth();\r\n        double height = bounds.isEmpty() ? 0 : bounds.getHeight();\r\n\r\n        if (terminator) {\r\n            x += width;\r\n            width = 0;\r\n        }\r\n\r\n        return new Rectangle2D(x, y, width, height);\r\n    }\r\n<\/pre>\n<p>\u3053\u306e\u30e1\u30bd\u30c3\u30c9\u306f\u6307\u5b9a\u3055\u308c\u305f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u3042\u308b\u6587\u5b57\u306e\u5883\u754c\u3092\u8fd4\u3057\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3067\u5168\u3066\u30af\u30ea\u30a2\u3067\u3059\u3002<\/p>\n<pre title=\"HitInfoWord.java\">    \/\/ Rectangle2D \r\n    private double x;\r\n    private double y;\r\n    private double width;\r\n    private double height;\r\n\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\r\n            \/\/ \u6587\u5b57\u304a\u3088\u3073 Rectangle2D \u30c7\u30fc\u30bf\u53d6\u5f97\r\n            word = null;\r\n            Optional.ofNullable(morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()))\r\n                    .ifPresent(morpheme -&gt; {\r\n                        word = morpheme.word;\r\n\r\n                        int startIndex = morpheme.start;\r\n                        Rectangle2D startRect = textAreaSkin.getCharacterBounds(startIndex);\r\n                        int endIndex = morpheme.end;\r\n                        if (endIndex &gt; 0) {\r\n                            endIndex--;\r\n                        }\r\n                        Rectangle2D endRect = textAreaSkin.getCharacterBounds(endIndex);\r\n                        \/\/ OnMouse Word Rect Coordinate\r\n                        x = startRect.getMinX() + textArea.getPadding().getLeft();\r\n                        y = startRect.getMinY() + textArea.getPadding().getTop();\r\n                        width = endRect.getMaxX() - startRect.getMinX();\r\n                        height = startRect.getHeight();\r\n                    });\r\n\r\n            \/\/ TextArea \u30b3\u30f3\u30c6\u30f3\u30c4\u5185\u3067\u6587\u5b57\u4e0a\u306b\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u3042\u308b\u5834\u5408\u306b Tooltip\u3001Rect \u3092\u8868\u793a\r\n            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null\r\n                    &amp;&amp; e.getX() &gt; x\r\n                    &amp;&amp; e.getY() &gt; y\r\n                    &amp;&amp; e.getX() &lt; x + width\r\n                    &amp;&amp; e.getY() &lt; y + height\r\n                    &amp;&amp; e.getX() &gt; textArea.getPadding().getLeft() + leftInset\r\n                    &amp;&amp; e.getY() &gt; textArea.getPadding().getTop() + topInset\r\n                    &amp;&amp; e.getX() &lt; textArea.getWidth() - textArea.getPadding().getRight() - leftInset\r\n                    &amp;&amp; e.getY() &lt; textArea.getHeight() - textArea.getPadding().getBottom() - topInset) {\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n\r\n<\/pre>\n<p>\u6587\u5b57\u306e\u6700\u5f8c\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f\u305d\u306e\u307e\u307e\u3060\u3068\u4e00\u3064\u591a\u304f\u306a\u3063\u3066\u3057\u307e\u3046\u306e\u3067 -1 \u30aa\u30d5\u30bb\u30c3\u30c8\u3057\u3066\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/10.jpg\"><img loading=\"lazy\" decoding=\"async\" title=\"10\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"10\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/10_thumb.jpg\" width=\"644\" height=\"302\"><\/a><\/p>\n<p>\u6700\u7d42\u7684\u306b\u306f TextArea \u306e\u80cc\u666f\u3092\u900f\u660e\u306b\u3057\u3066\u305d\u306e\u4e0b\u306b Canvas \u3092\u7f6e\u304d\u9078\u629e\u3055\u308c\u305f\u6587\u5b57\u306e Rectangle2D \u30c7\u30fc\u30bf\u3092\u4f7f\u3063\u3066 \u6587\u5b57\u3092\u56f2\u3080\u3088\u3046\u306b Rectangle \u3092\u8868\u793a\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/hit600.gif\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"hit600\" style=\"display: inline\" alt=\"hit600\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/hit600_thumb.gif\" width=\"600\" height=\"364\"><\/a><\/p>\n<p>\u3053\u308c\u3067\u5168\u3066\u306e\u554f\u984c\u306f\u89e3\u6c7a\uff01\u3000\u3081\u3067\u305f\u3057\uff01\u3000\u3081\u3067\u305f\u3057\uff01<\/p>\n<p>\u6700\u7d42\u7684\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u30b3\u30fc\u30c9\u306f\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>jp.yucchi.Dictionary4MorphologicalAnalysis \u30d1\u30c3\u30b1\u30fc\u30b8\u306f\u305d\u306e\u307e\u307e\u5909\u66f4\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n<pre title=\"HitInfoWord.java\">package jp.yucchi.hitinfoword;\r\n\r\nimport com.sun.javafx.scene.control.skin.TextAreaSkin;\r\nimport com.sun.javafx.scene.text.HitInfo;\r\nimport java.io.PrintWriter;\r\nimport java.io.StringWriter;\r\nimport java.lang.reflect.Field;\r\nimport java.util.Optional;\r\nimport java.util.logging.Level;\r\nimport java.util.logging.Logger;\r\nimport javafx.animation.KeyFrame;\r\nimport javafx.animation.Timeline;\r\nimport javafx.application.Application;\r\nimport static javafx.application.Application.launch;\r\nimport javafx.application.Platform;\r\nimport javafx.geometry.Insets;\r\nimport javafx.geometry.Rectangle2D;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.canvas.Canvas;\r\nimport javafx.scene.canvas.GraphicsContext;\r\nimport javafx.scene.control.Alert;\r\nimport javafx.scene.control.ButtonType;\r\nimport javafx.scene.control.TextArea;\r\nimport javafx.scene.control.Tooltip;\r\nimport javafx.scene.layout.StackPane;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.text.Text;\r\nimport javafx.stage.Stage;\r\nimport javafx.stage.StageStyle;\r\nimport javafx.util.Duration;\r\nimport jp.yucchi.Dictionary4MorphologicalAnalysis.MorphologicalAnalysis;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class HitInfoWord extends Application {\r\n\r\n    private final MorphologicalAnalysis morphologicalAnalysis = new MorphologicalAnalysis();\r\n\r\n    private String word;\r\n\r\n    private final boolean debug = true;\r\n\r\n    \/\/ Tooltip Timer\r\n    private static final int TOOLTIP_ACTIVATION_TIME = 500;\r\n    private static final int TOOLTIP_HIDE_TIME = 10_000;\r\n\r\n    \/\/ TextArea Default Inset\r\n    private double leftInset;\r\n    private double topInset;\r\n\r\n    private static final String TEXT_DATA = \"Minimal Value Types\\n\"\r\n            + \"\\n\"\r\n            + \"The specific features of our minimum (but viable) support for value types can be summarized as follows:\\n\"\r\n            + \"A few value-capable classes (Int128, etc.) from which the VM may derive value types. \"\r\n            + \"These can be standard POJO class files.\\n\"\r\n            + \"Descriptor syntax (\u201cQ-types\u201d) for describing new value types in class-files.\\n\"\r\n            + \"Enhanced constants in the constant pool, to interoperate with these descriptors.\\n\"\r\n            + \"Three bytecode instructions (vload, etc.) for moving value types between JVM locals and stack.\\n\"\r\n            + \"Limited reflection for value types (similar to int.class).\\n\"\r\n            + \"Boxing and unboxing, to represent values (like primitives) in terms of Java\u2019s universal Object type.\\n\"\r\n            + \"Method handle factories to provide access to value operations (member access, etc.)\\n\"\r\n            + \"Standard Java source code, including generic classes and methods, \"\r\n            + \"will be able to refer to values only in their boxed form. \"\r\n            + \"However, both method handles and specially-generated bytecodes \"\r\n            + \"will be able to work with values in their native, unboxed form.\\n\"\r\n            + \"This work relates to the JVM, not to the language. Therefore non-goals include:\\n\"\r\n            + \"Syntax for defining or using value types directly from Java code.\\n\"\r\n            + \"Specialized generics in Java code which can store or process unboxed values (or primitives).\\n\"\r\n            + \"Library value types or evolved versions of value-based classes like java.util.Optional.\\n\"\r\n            + \"Access to value types from arbitrary modules. (Typically, value-capable classes will not be exported.)\\n\"\r\n            + \"Given the slogan \u201ccodes like a class, works like an int,\u201d \"\r\n            + \"which captures the overall vision for value types, this minimal set will deliver something more like \"\r\n            + \"\u201cworks like an int, if you can catch one\u201d.\\n\"\r\n            + \"By limiting the scope of this work, we believe useful experimentation can be enabled in a production \"\r\n            + \"JVM much earlier than if the entire value-type stack were delivered all at once.\\n\"\r\n            + \"The rest of this document goes into the proposed features in detail.\";\r\n\r\n    \/\/ Rectangle2D \r\n    private double x;\r\n    private double y;\r\n    private double width;\r\n    private double height;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n        int sceneWidth = 800;\r\n        int sceneHeight = 250;\r\n\r\n        StackPane root = new StackPane();\r\n\r\n        Canvas canvas = new Canvas(sceneWidth, sceneHeight);\r\n        GraphicsContext gc = canvas.getGraphicsContext2D();\r\n        gc.setStroke(Color.BLUE);\r\n        gc.setLineWidth(3);\r\n\r\n        TextArea textArea = new TextArea();\r\n        textArea.setWrapText(true);\r\n        textArea.setEditable(false);\r\n        textArea.setStyle(\"-fx-text-fill: black;\" + \"-fx-font-weight: normal;\" + \"-fx-font-size: 24;\");\r\n        textArea.setPadding(new Insets(50, 50, 50, 50)); \/\/(top\/right\/bottom\/left)\r\n        textArea.setText(TEXT_DATA);\r\n\r\n        final Tooltip tooltip = new Tooltip();\r\n        myTooltipTimer(tooltip);\r\n\r\n        try {\r\n            Optional&lt;String&gt; text = Optional.ofNullable(textArea.getText());\r\n            morphologicalAnalysis.setText(text.orElseThrow((() -&gt; new Exception())));\r\n        } catch (Exception ex) {\r\n            exceptionOccured(ex);\r\n        }\r\n\r\n        textArea.layoutBoundsProperty().addListener(e -&gt; {\r\n            textArea.setScrollTop(0);\r\n            gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n            gc.setFill(Color.WHITE);\r\n            gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n        });\r\n\r\n        textArea.setOnMouseExited(e -&gt; {\r\n            gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n            gc.setFill(Color.WHITE);\r\n            gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n        });\r\n\r\n        textArea.scrollTopProperty().addListener(e -&gt; {\r\n            gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n            gc.setFill(Color.LIGHTYELLOW);\r\n            gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n            Tooltip.uninstall(textArea, tooltip);\r\n        });\r\n\r\n        textArea.setOnMouseMoved(e -&gt; {\r\n            TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n            HitInfo hitInfo = textAreaSkin.getIndex(e.getX() - textArea.getPadding().getLeft(),\r\n                    e.getY() + textArea.scrollTopProperty().getValue() - textArea.getPadding().getTop());\r\n\r\n            gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n            gc.setFill(Color.LIGHTYELLOW);\r\n            gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n\r\n            \/\/ \u6587\u5b57\u304a\u3088\u3073 Rectangle2D \u30c7\u30fc\u30bf\u53d6\u5f97\r\n            word = null;\r\n            Optional.ofNullable(morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()))\r\n                    .ifPresent(morpheme -&gt; {\r\n                        word = morpheme.word;\r\n\r\n                        int startIndex = morpheme.start;\r\n                        Rectangle2D startRect = textAreaSkin.getCharacterBounds(startIndex);\r\n                        int endIndex = morpheme.end;\r\n                        if (endIndex &gt; 0) {\r\n                            endIndex--;\r\n                        }\r\n                        Rectangle2D endRect = textAreaSkin.getCharacterBounds(endIndex);\r\n                        \/\/ OnMouse Word Rect Coordinate\r\n                        x = startRect.getMinX() + textArea.getPadding().getLeft();\r\n                        y = startRect.getMinY() + textArea.getPadding().getTop();\r\n                        width = endRect.getMaxX() - startRect.getMinX();\r\n                        height = startRect.getHeight();\r\n                    });\r\n\r\n            \/\/ TextArea \u30b3\u30f3\u30c6\u30f3\u30c4\u5185\u3067\u6587\u5b57\u4e0a\u306b\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u3042\u308b\u5834\u5408\u306b Tooltip\u3001Rect \u3092\u8868\u793a\r\n            if (morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()) != null\r\n                    &amp;&amp; e.getX() &gt; x\r\n                    &amp;&amp; e.getY() &gt; y\r\n                    &amp;&amp; e.getX() &lt; x + width\r\n                    &amp;&amp; e.getY() &lt; y + height\r\n                    &amp;&amp; e.getX() &gt; textArea.getPadding().getLeft() + leftInset\r\n                    &amp;&amp; e.getY() &gt; textArea.getPadding().getTop() + topInset\r\n                    &amp;&amp; e.getX() &lt; textArea.getWidth() - textArea.getPadding().getRight() - leftInset\r\n                    &amp;&amp; e.getY() &lt; textArea.getHeight() - textArea.getPadding().getBottom() - topInset) {\r\n                gc.setFill(Color.LIGHTYELLOW);\r\n                gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n                gc.strokeRoundRect(x, y, width, height, 10, 10);\r\n                Tooltip.install(textArea, tooltip);\r\n            } else {\r\n                Tooltip.uninstall(textArea, tooltip);\r\n            }\r\n\r\n            tooltip.setText(\"X: \" + e.getX() + \"\\n\"\r\n                    + \"Y: \" + (e.getY() + textArea.scrollTopProperty().getValue()) + \"\\n\"\r\n                    + \"getCharIndex: \" + hitInfo.getCharIndex() + \"\\n\"\r\n                    + \"getInsertionIndex: \" + hitInfo.getInsertionIndex() + \"\\n\"\r\n                    + \"isLeading: \" + hitInfo.isLeading() + \"\\n\"\r\n                    + word);\r\n\r\n            if (debug) {\r\n                System.out.println(\"X: \" + e.getX() + \"\\n\"\r\n                        + \"Y: \" + (e.getY() + textArea.scrollTopProperty().getValue()) + \"\\n\"\r\n                        + \"getCharIndex: \" + hitInfo.getCharIndex() + \"\\n\"\r\n                        + \"getInsertionIndex: \" + hitInfo.getInsertionIndex() + \"\\n\"\r\n                        + \"isLeading: \" + hitInfo.isLeading() + \"\\n\"\r\n                        + word + \"\\n\");\r\n            }\r\n\r\n        });\r\n\r\n        root.getChildren().addAll(canvas, textArea);\r\n        Scene scene = new Scene(root, sceneWidth, sceneHeight);\r\n        scene.getStylesheets().add(getClass().getResource(\"myCSS.css\").toExternalForm());\r\n\r\n        canvas.widthProperty().bind(textArea.widthProperty());\r\n        canvas.heightProperty().bind(textArea.heightProperty());\r\n\r\n        primaryStage.setTitle(this.getClass().getSimpleName());\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n\r\n        gc.setFill(Color.WHITE);\r\n        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());\r\n\r\n        Text textNode = (Text) textArea.lookup(\".text\");\r\n        \/\/ TextArea Default Inset \u53d6\u5f97\r\n        leftInset = textNode.getLayoutX();\r\n        topInset = textNode.getLayoutY();\r\n\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n    \/\/ TooltipTimer \u5909\u66f4\r\n    private void myTooltipTimer(Tooltip tooltip) {\r\n        try {\r\n            Field fieldBehavior = tooltip.getClass().getDeclaredField(\"BEHAVIOR\");\r\n            fieldBehavior.setAccessible(true);\r\n            Object objBehavior = fieldBehavior.get(tooltip);\r\n\r\n            Field activationTimer = objBehavior.getClass().getDeclaredField(\"activationTimer\");\r\n            activationTimer.setAccessible(true);\r\n\r\n            Timeline activationTimeline = (Timeline) activationTimer.get(objBehavior);\r\n            activationTimeline.getKeyFrames().clear();\r\n            activationTimeline.getKeyFrames().add(new KeyFrame(new Duration(TOOLTIP_ACTIVATION_TIME)));\r\n\r\n            Field hideTimer = objBehavior.getClass().getDeclaredField(\"hideTimer\");\r\n            hideTimer.setAccessible(true);\r\n\r\n            Timeline hideTimeline = (Timeline) hideTimer.get(objBehavior);\r\n            hideTimeline.getKeyFrames().clear();\r\n            hideTimeline.getKeyFrames().add(new KeyFrame(new Duration(TOOLTIP_HIDE_TIME)));\r\n        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {\r\n            Logger.getLogger(HitInfoWord.class.getName()).log(Level.SEVERE, null, ex);\r\n            exceptionOccured(ex);\r\n        }\r\n    }\r\n\r\n    private void exceptionOccured(Exception ex) {\r\n        Alert alert = new Alert(Alert.AlertType.ERROR);\r\n\r\n        StringWriter sw = new StringWriter();\r\n        PrintWriter pw = new PrintWriter(sw);\r\n        ex.printStackTrace(pw);\r\n        pw.flush();\r\n        String stackTrace = sw.toString();\r\n\r\n        TextArea textArea = new TextArea(stackTrace);\r\n        textArea.setEditable(false);\r\n        alert.getDialogPane().setExpandableContent(textArea);\r\n        alert.initStyle(StageStyle.TRANSPARENT);\r\n\/\/            alert.setTitle(\"ERROR\");\r\n        alert.setHeaderText(\"Error!\\n\" + ex.getClass().getSimpleName());\r\n        alert.setContentText(\"Exit the application.\");\r\n        alert.showAndWait()\r\n                .filter(response -&gt; response == ButtonType.OK)\r\n                .ifPresent(response -&gt; {\r\n                    Platform.exit();\r\n                    System.exit(0);\r\n                });\r\n    }\r\n\r\n}\r\n\r\n<\/pre>\n<pre title=\"myCSS.css\">\/* \r\n    Author     : Yucchi\r\n*\/\r\n\r\n.text-area .content{\r\n    -fx-background-color: transparent;\r\n}\r\n\r\n.text-area {\r\n    -fx-background-color: transparent;\r\n}\r\n\r\n.text-area .scroll-pane {\r\n    -fx-background-color: transparent;\r\n}\r\n\r\n.text-area .scroll-pane .viewport{\r\n    -fx-background-color: transparent;\r\n}\/*\r\n\r\n\r\n*\/.text-area .scroll-pane .content{\r\n    -fx-background-color: transparent;\r\n} \r\n\r\n.text-area *.text {\r\n    -fx-text-alignment: center;\r\n}\r\n\r\n.scroll-bar:vertical {\r\n    -fx-background-color: TRANSPARENT;\r\n}\r\n\r\n.scroll-bar:vertical *.thumb {\r\n    -fx-background-color: pink;\r\n}\r\n\r\n.scroll-bar:vertical *.track {\r\n    -fx-background-color: TRANSPARENT;\r\n}\r\n\r\n.scroll-bar *.increment-button {\r\n    -fx-background-color: TRANSPARENT;\r\n}\r\n\r\n.scroll-bar *.decrement-button {\r\n    -fx-background-color: TRANSPARENT;\r\n}\r\n\r\n.scroll-bar:vertical *.increment-arrow {\r\n    -fx-background-color: hotpink;\r\n}\r\n\r\n.scroll-bar:vertical *.decrement-arrow {\r\n    -fx-background-color: hotpink;\r\n}\r\n\r\n.scroll-bar:vertical .thumb:hover,\r\n.scroll-bar:vertical .thumb:pressed{\r\n    -fx-background-color: linear-gradient(from 0% 0% to 100% 0%,hotpink 0%, white 50%, hotpink 100%);\r\n}\r\n\r\n.scroll-bar:vertical *.increment-arrow:hover {\r\n    -fx-background-color: aqua;\r\n}\r\n\r\n.scroll-bar:vertical *.decrement-arrow:hover {\r\n    -fx-background-color: aqua;\r\n}\r\n\r\n.scroll-bar:vertical *.increment-arrow:pressed {\r\n    -fx-background-color: red;\r\n}\r\n\r\n.scroll-bar:vertical *.decrement-arrow:pressed {\r\n    -fx-background-color: red;\r\n}\r\n<\/pre>\n<p>HitInfo \u306b\u3064\u3044\u3066\u5c11\u3057\u3060\u3051\u30fb\u30fb\u30fb\u306e\u306f\u305a\u304c\u3060\u3089\u3060\u3089\u9577\u304f\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3057\u305f\u3002<\/p>\n<p>\u4eca\u56de\u306f\u3053\u306e\u3088\u3046\u306a\u884c\u304d\u5f53\u305f\u308a\u3070\u3063\u305f\u308a\u306e\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u3067\u6ce3\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u8a66\u3057\u3066\u306a\u3044\u306e\u3067\u3042\u308c\u306a\u3093\u3067\u3059\u304c\u3001<\/p>\n<p>TextArea \u30af\u30e9\u30b9\u306e public ObservableList&lt;CharSequence&gt; getParagraphs() \u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3063\u3066\u6587\u5b57\u30ea\u30b9\u30c8\u3092\u53d6\u5f97\u3057\u3066<\/p>\n<p>TextAreaSkin \u30af\u30e9\u30b9\u306e public Rectangle2D getCharacterBounds(int index) \u30e1\u30bd\u30c3\u30c9\u306b\u6e21\u3057\u3066\u5404\u6587\u5b57\u306e\u9818\u57df\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u3066\u304b\u3089<\/p>\n<p>TextArea \u5185\u306e\u30ab\u30fc\u30bd\u30eb\u306e\u4f4d\u7f6e\u304c\u6587\u5b57\u9818\u57df\u5185\u306b\u3042\u308b\u3068\u304d\u3060\u3051 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3059\u308b\u3088\u3046\u306b\u3057\u305f\u307b\u3046\u304c\u826f\u3044\u306e\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n<p>\u8ab0\u304b\u8208\u5473\u3068\u6642\u9593\u306e\u3042\u308b\u4eba\u306f\u304a\u8a66\u3057\u3092\uff01<\/p>\n<p>TextArea \u30af\u30e9\u30b9\u3092\u4f7f\u3063\u3066 HitInfo \u30af\u30e9\u30b9\u3092\u8a66\u3057\u3066\u307f\u307e\u3057\u305f\u304c TextField \u30af\u30e9\u30b9\u3067\u3082 HitInfo \u30af\u30e9\u30b9\u306f\u4f7f\u3048\u307e\u3059\u3002<\/p>\n<p>TextFieldSkin \u30af\u30e9\u30b9\u306b\u3082 public HitInfo getIndex(double x, double y) \u30e1\u30bd\u30c3\u30c9\u304c\u7528\u610f\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u4eca\u56de\u8a66\u3057\u3066\u307f\u305f TextArea \u30af\u30e9\u30b9\u540c\u69d8\u306b\u304a\u3082\u3057\u308d\u305d\u3046\u306a\u3053\u3068\u304c\u3067\u304d\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n<p>\u3057\u304b\u3057\u3001\u305d\u308c\u3088\u308a\u3082\u6c17\u306b\u306a\u308b\u306e\u304c JavaFX 9 \u3067 javafx.graphics \u30e2\u30b8\u30e5\u30fc\u30eb\u306e javafx.scene.text \u30d1\u30c3\u30b1\u30fc\u30b8\u306b\u3042\u308b Text \u30af\u30e9\u30b9\u306b <\/p>\n<p>HitInfo \u3092\u8fd4\u3059 public final HitInfo hitTest(Point2D point) \u30e1\u30bd\u30c3\u30c9\u304c\u7528\u610f\u3055\u308c\u305f\u3053\u3068\u3067\u3059\u3002<\/p>\n<p>\u3042\u3068\u540c\u30d1\u30c3\u30b1\u30fc\u30b8\u306b\u3042\u308b TextFlow \u30af\u30e9\u30b9\u306b\u3082 HitInfo \u3092\u8fd4\u3059 public final HitInfo hitTest(Point2D point) \u30e1\u30bd\u30c3\u30c9\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>TextFlow \u30af\u30e9\u30b9\u306e\u307b\u3046\u306f TextArea \u30af\u30e9\u30b9\u3068\u540c\u3058\u3088\u3046\u306a\u3082\u306e\u3060\u3068\u60f3\u50cf\u3067\u304d\u307e\u3059\u3002<\/p>\n<p>\u3057\u304b\u3057\u3001Text \u30af\u30e9\u30b9\u306e\u307b\u3046\u306f\u3061\u3087\u3063\u3068\u6c17\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u3055\u3089\u306b JavaFX 9 \u3067\u306f\u30ad\u30e3\u30ec\u30c3\u30c8\u3092\u6307\u5b9a\u3055\u308c\u305f\u4f4d\u7f6e\u306b\u79fb\u52d5\u3055\u305b\u308b\u305f\u3081\u306e\u30e1\u30bd\u30c3\u30c9\u304c TextAreaSkin \u30af\u30e9\u30b9\u3068 TextFieldSkin \u30af\u30e9\u30b9\u306b\u7528\u610f\u3055\u308c\u307e\u3057\u305f\u3002<\/p>\n<p>public void positionCaret(HitInfo hit, boolean select)<\/p>\n<p>\u3053\u308c\u306f\u3061\u3087\u3063\u3068\u8a66\u3057\u305f\u304f\u306a\u308a\u307e\u3059\u3088\u306d\uff01<\/p>\n<p>\u305d\u3053\u3067 Text \u30ce\u30fc\u30c9\u306e\u5358\u8a9e\u3092\u9078\u629e\u3057\u3066 TextArea \u306e\u866b\u98df\u3044\u6587\u306b\u30c9\u30e9\u30c3\u30b0\u30a2\u30f3\u30c9\u30c9\u30ed\u30c3\u30d7\u3059\u308b\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u4f5c\u3063\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/starwas_6001.gif\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"starwas_600[1]\" style=\"display: inline\" alt=\"starwas_600[1]\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/starwas_6001_thumb.gif\" width=\"600\" height=\"364\"><\/a><\/p>\n<p>Text \u30ce\u30fc\u30c9\u304b\u3089\u5358\u8a9e\u3092\u9078\u629e\u3059\u308b\u306e\u306f\u5148\u307b\u3069\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3068\u4ed5\u7d44\u307f\u306f\u307b\u307c\u540c\u3058\u3067\u3059\u3002<\/p>\n<p>JavaFX 9 \u3067\u8ffd\u52a0\u3055\u308c\u305f\u65b0\u3057\u3044\u6a5f\u80fd\u3092\u4f7f\u3046\u306b\u306f\u3069\u3046\u3059\u308c\u3070\u3044\u3044\u306e\u3067\u3057\u3087\u3046\u304b\u3002<\/p>\n<p>\u307e\u305a\u3001JDK9 Early Access Releases \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3066\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3002<\/p>\n<p><a title=\"https:\/\/jdk9.java.net\/download\/\" href=\"https:\/\/jdk9.java.net\/download\/\">https:\/\/jdk9.java.net\/download\/<\/a><\/p>\n<p>\u3042\u3068\u306f\u304a\u6c17\u306b\u5165\u308a\u306e\u30a8\u30c7\u30a3\u30bf\u304b IDE \u3067\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u7d44\u3093\u3067\u3044\u304d\u307e\u3059\u3002<\/p>\n<p>JDK9 \u3067\u306f Project Jigsaw \u306e\u5f71\u97ff\u3067 com.sun \u304b\u3089\u59cb\u307e\u308b\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u540d\u524d\u304c\u5909\u66f4\u306b\u306a\u3063\u3066\u3044\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u4eca\u56de\u306f\u6b21\u306e\u4e8c\u3064\u306e\u30d1\u30c3\u30b1\u30fc\u30b8\u304c\u5909\u66f4\u3055\u308c\u3066\u3044\u307e\u3057\u305f\u3002<\/p>\n<p>com.sun.javafx.scene.control.skin.TextAreaSkin; \/\/ JavaFX8<br \/>com.sun.javafx.scene.text.HitInfo; \/\/ JavaFX 8<br \/>javafx.scene.control.skin.TextAreaSkin; \/\/ JavaFX 9<br \/>javafx.scene.text.HitInfo; \/\/ JavaFX 9<\/p>\n<p>\u3055\u3066\u3001\u5358\u8a9e\u3092\u9078\u629e\u3055\u308c\u308b\u5074\u306e Text \u30ce\u30fc\u30c9\u304b\u3089 hitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3059\u308b\u305f\u3081\u306b public final HitInfo hitTest(Point2D point) \u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3044\u307e\u3059\u3002<\/p>\n<p>\u5f15\u6570\u306e Point2D point \u306f\u30b3\u30f3\u30c6\u30ca\u306e TextFlow \u306b\u304a\u3051\u308bText \u30ce\u30fc\u30c9\u306e\u5ea7\u6a19\u3067\u3059\u3002\uff08Text \u30ce\u30fc\u30c9\u4e0a\u306b\u3042\u308b\u30de\u30a6\u30b9\u30dd\u30a4\u30f3\u30bf\u306e\u4f4d\u7f6e\uff09<\/p>\n<p>\u611f\u306e\u3044\u3044\u4eba\u306a\u3089\u6c17\u3065\u3044\u3066\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u304c\u3001\u3053\u308c\u4f55\u6c17\u306b\u3046\u308c\u3057\u3044\u3067\u3059\u306d\uff01<\/p>\n<pre title=\"HitInfoInJavaFX9.java\">        textFlow.setOnMousePressed(e -&gt; {\r\n            HitInfo hitInfo = text.hitTest(new Point2D(e.getX() - text.getTranslateX(), e.getY() - text.getTranslateY()));\r\n<\/pre>\n<p>\u305d\u3046\u3001\u30b3\u30f3\u30c6\u30ca\u306e TextFlow \u3058\u3083\u306a\u304f\u3066 Text \u30ce\u30fc\u30c9\u3067 hitTest(Point2D point) \u30e1\u30bd\u30c3\u30c9\u3092\u5b9f\u884c\u3057\u3066 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>Text \u30ce\u30fc\u30c9\u4e0a\u3067\u306a\u3044\u3068 HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u751f\u6210\u3055\u308c\u306a\u3044\u3093\u3067\u3059\u306d\u3002<\/p>\n<p>\u3082\u3046\u4f59\u767d\u306e\u3053\u3068\u306f\u8003\u3048\u306a\u304f\u3066\u3044\u3044\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u3057\u304b\u3057\u3001Text \u30ce\u30fc\u30c9\u3092\u79fb\u52d5\u3055\u305b\u305f\u5834\u5408\u30de\u30c3\u30d4\u30f3\u30b0\u304c\u72c2\u3063\u3066\u3057\u307e\u3046\u306e\u3067\u305d\u306e\u88dc\u6b63\u306f\u5fc5\u8981\u3067\u3059\u3002<\/p>\n<p>\u4e0a\u8a18\u306e\u30b3\u30fc\u30c9\u306f X, Y \u5ea7\u6a19\u306e\u79fb\u52d5\u3092\u8003\u616e\u3057\u3066 getTranslateX(),&nbsp; text.getTranslateY() \u30e1\u30bd\u30c3\u30c9\u3092\u5229\u7528\u3057\u3066\u3044\u307e\u3059\u3002\uff08\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u306f getTranslateX() \u306f\u5fc5\u8981\u306a\u3044\u3067\u3059\u3002\uff09<\/p>\n<p>\u6b21\u306b JavaFX 9 \u306e\u65b0\u6a5f\u80fd\u3092\u4f7f\u3048\u308b\u3068\u3053\u308d\u306f\u9078\u629e\u3055\u308c\u305f Text \u30ce\u30fc\u30c9\u306e\u5358\u8a9e\u3092\u30c9\u30e9\u30c3\u30b0\u30a2\u30f3\u30c9\u30c9\u30ed\u30c3\u30d7\u3059\u308b\u6642\u3067\u3059\u306d\u3002<\/p>\n<p>Text \u30ce\u30fc\u30c9\u306e\u5358\u8a9e\u3092\u30c9\u30e9\u30c3\u30b0\u3067 TextArea \u5185\u306e\u6587\u5b57\u5217\u306e\u4efb\u610f\u306e\u5834\u6240\u3092\u9078\u629e\u3057\u3066\u30ad\u30e3\u30ec\u30c3\u30c8\u3092\u79fb\u52d5\u3055\u305b\u308b\u305f\u3081\u306e\u51e6\u7406\u3067\u3059\u3002<\/p>\n<pre title=\"HitInfoInJavaFX9.java\">        textArea.setOnDragOver(e -&gt; {\r\n            if (e.getGestureSource() != textArea\r\n                    &amp;&amp; e.getDragboard().hasString()) {\r\n                e.acceptTransferModes(TransferMode.COPY_OR_MOVE);\r\n                TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n                HitInfo hitInfo = textAreaSkin.getIndex(e.getX(), e.getY() + textArea.scrollTopProperty().getValue());\r\n\/\/                int insertionPoint = hitInfo.getInsertionIndex(); \/\/ JavaFX 8\r\n\/\/                textArea.positionCaret(insertionPoint); \/\/ JavaFX 8\r\n                textAreaSkin.positionCaret(hitInfo, false); \/\/ JavaFX 9\r\n            }\r\n            e.consume();\r\n        });\r\n<\/pre>\n<p>\u3053\u308c\u306f JavaFX 8 \u306e\u5834\u5408\u306f\u30b3\u30e1\u30f3\u30c8\u30a2\u30a6\u30c8\u3057\u3066\u3042\u308b\u30b3\u30fc\u30c9\u3067\u3044\u3051\u307e\u3059\u3002<\/p>\n<p>JavaFX 9 \u306a\u3089\u3082\u3063\u3068\u30b9\u30de\u30fc\u30c8\u306b\u51e6\u7406\u30b3\u30fc\u30c9\u304c\u66f8\u3051\u3066\u3057\u307e\u3044\u307e\u3059\u3002<\/p>\n<p>TextAreaSkin \u30af\u30e9\u30b9\u306e public void positionCaret(HitInfo hit, boolean select) \u30e1\u30bd\u30c3\u30c9\u304c\u512a\u79c0\u3067\u3059\u3002<\/p>\n<p>\u3053\u306e\u30e1\u30bd\u30c3\u30c9\u306e\u7b2c\u4e00\u5f15\u6570\u306f HitInfo \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3067\u3059\u3002\u7b2c\u4e8c\u5f15\u6570\u304c\u4f55\u304b\u6c17\u306b\u306a\u308a\u307e\u3059\u306d\u3002<\/p>\n<p>API \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306b\u3088\u308b\u3068 whether to extend selection to the new position. \u3068\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u30aa\u30ec\u30aa\u30ec\u7ffb\u8a33\u3092\u3059\u308b\u3068\u300c\u9078\u629e\u3092\u65b0\u3057\u3044\u4f4d\u7f6e\u306b\u62e1\u5f35\u3059\u308b\u3079\u304d\u304b\u3069\u3046\u304b\u3002\u300d\u3067\u3059\u304b\u306d\uff1f<\/p>\n<p>\u3053\u3046\u3044\u3046\u3068\u304d\u306f\u8a66\u3057\u3066\u52d5\u4f5c\u78ba\u8a8d\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<p>\u7b2c\u4e8c\u5f15\u6570\u306e\u5024\u3092 true \u306b\u8a2d\u5b9a\u3057\u3066\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u52d5\u4f5c\u78ba\u8a8d\u3092\u884c\u3044\u307e\u3059\u3002<\/p>\n<p>\u3061\u3087\u3063\u3068\u898b\u3065\u3089\u3044\u3067\u3059\u3051\u3069 TextArea \u5185\u306e\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u4e00\u756a\u5de6\u7aef\u306e\u4e0a\u90e8\u306e\u9685\u306b\u3042\u308a\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/11.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"11\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"11\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/11_thumb.jpg\" width=\"644\" height=\"234\"><\/a><\/p>\n<p>Text \u30ce\u30fc\u30c9\u304b\u3089\u5358\u8a9e\u3092\u9078\u3093\u3067\u30c9\u30e9\u30c3\u30b0\u3057\u3066\u3044\u307e\u3059\u3002\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u30de\u30a6\u30b9\u30dd\u30a4\u30f3\u30bf\u306e\u3042\u308b\u4f4d\u7f6e\u307e\u3067\u79fb\u52d5\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u306f\u3058\u3081\u306b\u30ad\u30e3\u30ec\u30c3\u30c8\u304c\u3042\u3063\u305f\u5834\u6240\u304b\u3089\u65b0\u305f\u306b\u79fb\u52d5\u3057\u305f\u5834\u6240\u307e\u3067\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u308b\u72b6\u614b\u3068\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/12.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"12\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"12\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/12_thumb.jpg\" width=\"644\" height=\"209\"><\/a><\/p>\n<p>\u4eca\u5ea6\u306f\u30ad\u30e3\u30ec\u30c3\u30c8\u306e\u4f4d\u7f6e\u3092 All \u3068\u3044\u3046\u5358\u8a9e\u306e\u5de6\u96a3\u307e\u3067\u79fb\u52d5\u3055\u305b\u3066\u304a\u304d\u307e\u3057\u305f\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/13.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"13\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"13\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/13_thumb.jpg\" width=\"644\" height=\"231\"><\/a><\/p>\n<p>\u4eca\u5ea6\u306f\u305d\u3053\u304b\u3089\u30c9\u30e9\u30c3\u30b0\u64cd\u4f5c\u306b\u3088\u308a\u65b0\u305f\u306a\u30ad\u30e3\u30ec\u30c3\u30c8\u306e\u4f4d\u7f6e\u307e\u3067\u9078\u629e\u8868\u793a\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/14.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"14\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"14\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/14_thumb.jpg\" width=\"644\" height=\"223\"><\/a><\/p>\n<p>\u7b2c\u4e8c\u5f15\u6570\u304c true \u306e\u6642\u306e\u52d5\u4f5c\u306f\u30ad\u30e3\u30ec\u30c3\u30c8\u306e\u79fb\u52d5\u5148\u307e\u3067\u9078\u629e\u3059\u308b\u3088\u3046\u3067\u3059\u3002<\/p>\n<p>\u4eca\u56de\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u3053\u306e\u3088\u3046\u306a\u6a5f\u80fd\u306f\u5fc5\u8981\u3068\u3057\u306a\u3044\u306e\u3067 false \u3068\u8a2d\u5b9a\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u75d2\u3044\u3068\u3053\u308d\u306b\u624b\u304c\u5c4a\u304f\u3088\u3046\u306a\u5730\u5473\u306a\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3067\u3059\u306d\u3002<\/p>\n<p><a name=\"getCharacterBounds-int-\"><\/a><\/p>\n<p>\u3042\u307e\u308a\u3001\u6d3e\u624b\u306a API \u3067\u306f\u306a\u3044\u3067\u3059\u3051\u3069\u3053\u3046\u3044\u3046\u3053\u3068\u304c\u3067\u304d\u308b\u3088\u3046\u3067\u3059\u306d\u3002<\/p>\n<p>\u6700\u5f8c\u306b\u3053\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u30b3\u30fc\u30c9\u3092\u8f09\u305b\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<pre title=\"HitInfoInJavaFX9.java\">package jp.yucchi.hitinfoinjavafx9;\r\n\r\n\/\/import com.sun.javafx.scene.control.skin.TextAreaSkin; \/\/ JavaFX8\r\n\/\/import com.sun.javafx.scene.text.HitInfo; \/\/ JavaFX 8\r\nimport java.io.PrintWriter;\r\nimport java.io.StringWriter;\r\nimport java.util.Optional;\r\nimport java.util.stream.Collectors;\r\nimport javafx.application.Application;\r\nimport javafx.application.Platform;\r\nimport javafx.collections.ObservableList;\r\nimport javafx.geometry.Insets;\r\nimport javafx.geometry.Point2D;\r\nimport javafx.scene.Node;\r\nimport javafx.scene.Scene;\r\nimport javafx.scene.control.Alert;\r\nimport javafx.scene.control.ButtonType;\r\nimport javafx.scene.control.TextArea;\r\nimport javafx.scene.control.skin.TextAreaSkin; \/\/ JavaFX 9\r\nimport javafx.scene.input.ClipboardContent;\r\nimport javafx.scene.input.Dragboard;\r\nimport javafx.scene.input.TransferMode;\r\nimport javafx.scene.layout.HBox;\r\nimport javafx.scene.layout.Priority;\r\nimport javafx.scene.paint.Color;\r\nimport javafx.scene.text.Font;\r\nimport javafx.scene.text.FontSmoothingType;\r\nimport javafx.scene.text.HitInfo; \/\/ JavaFX 9\r\nimport javafx.scene.text.Text;\r\nimport javafx.scene.text.TextAlignment;\r\nimport javafx.scene.text.TextFlow;\r\nimport javafx.stage.Stage;\r\nimport javafx.stage.StageStyle;\r\nimport jp.yucchi.Dictionary4MorphologicalAnalysis.MorphologicalAnalysis;\r\n\r\n\/**\r\n *\r\n * @author Yucchi\r\n *\/\r\npublic class HitInfoInJavaFX9 extends Application {\r\n\r\n    private final MorphologicalAnalysis morphologicalAnalysis = new MorphologicalAnalysis();\r\n    private String word;\r\n\r\n    @Override\r\n    public void start(Stage primaryStage) {\r\n\r\n        double sceneWidth = 750;\r\n        double sceneHeight = 370;\r\n\r\n        HBox root = new HBox();\r\n        root.setStyle(\"-fx-background-color: #111111;\");\r\n\r\n        Text text = new Text(\"Force love know why believe\");\r\n        text.setFill(Color.YELLOW);\r\n        text.setFont(Font.loadFont(this.getClass().getResourceAsStream(\"resources\/fonts\/STARWARS.TTF\"), 18));\r\n        text.setFontSmoothingType(FontSmoothingType.LCD);\r\n\r\n        TextFlow textFlow = new TextFlow(text);\r\n        textFlow.setStyle(\"-fx-background-color: black;\");\r\n        textFlow.setTextAlignment(TextAlignment.CENTER);\r\n        textFlow.setMinWidth(text.boundsInParentProperty().getValue().getWidth() \/ 2);\r\n\r\n        ObservableList&lt;Node&gt; nodes = textFlow.getChildren();\r\n        String words = nodes.stream().map(e -&gt; ((Text) e).getText()).collect(Collectors.joining());\r\n        try {\r\n            Optional&lt;String&gt; wordsText = Optional.ofNullable(words);\r\n            morphologicalAnalysis.setText(wordsText.orElseThrow((() -&gt; new Exception())));\r\n        } catch (Exception ex) {\r\n            exceptionOccured(ex);\r\n        }\r\n\r\n        TextArea textArea = new TextArea();\r\n        textArea.setWrapText(true);\r\n        String textData = \"I (  ) you.\\n\"\r\n                + \"I (  ).\\n\"\r\n                + \"\\n\"\r\n                + \"All right. I'll give it a try.\\n\"\r\n                + \"Try not. Do or do not. There is no try.\\n\"\r\n                + \"I don't... I don't (  ) it.\\n\"\r\n                + \"That is (  ) you fail.\\n\"\r\n                + \"\\n\"\r\n                + \"May the (  ) be with you.\\n\";\r\n        textArea.setText(textData);\r\n        textArea.setStyle(\"-fx-text-fill: yellow;\");\r\n        textArea.setFont(Font.loadFont(this.getClass().getResourceAsStream(\"resources\/fonts\/STARWARS.TTF\"), 18));\r\n        double adjustmentWidth = 30;\r\n        textArea.setMaxWidth(sceneWidth \/ 2 + adjustmentWidth);\r\n\r\n        HBox.setMargin(textFlow, new Insets(10, 10, 10, 10));\r\n        HBox.setMargin(textArea, new Insets(10, 10, 10, 10));\r\n        HBox.setHgrow(textFlow, Priority.ALWAYS);\r\n\r\n        root.getChildren().addAll(textFlow, textArea);\r\n\r\n        Scene scene = new Scene(root, sceneWidth, sceneHeight);\r\n\r\n        primaryStage.setMinWidth(sceneWidth \/ 2);\r\n        primaryStage.setMinHeight(sceneHeight \/ 2);\r\n        primaryStage.setTitle(\"Complete the famous lines of Star Wars.\");\r\n        primaryStage.setScene(scene);\r\n        primaryStage.show();\r\n\r\n        textArea.lookup(\".content\").setStyle(\"-fx-background-color: black;\");\r\n        text.translateYProperty().bind(textFlow.heightProperty().\r\n                subtract(text.layoutBoundsProperty().get().getHeight()).divide(2));\r\n\r\n        textFlow.setOnMousePressed(e -&gt; {\r\n            HitInfo hitInfo = text.hitTest(new Point2D(e.getX() - text.getTranslateX(), e.getY() - text.getTranslateY()));\r\n            word = null;\r\n            Optional.ofNullable(morphologicalAnalysis.getMorpheme(hitInfo.getCharIndex()))\r\n                    .ifPresent(morpheme -&gt; {\r\n                        word = morpheme.word;\r\n                    });\r\n        });\r\n\r\n        text.setOnDragDetected(e -&gt; {\r\n            Dragboard dragboard = text.startDragAndDrop(TransferMode.ANY);\r\n            ClipboardContent clipboardContent = new ClipboardContent();\r\n            clipboardContent.putString(word);\r\n            dragboard.setContent(clipboardContent);\r\n            e.consume();\r\n        });\r\n\r\n        textArea.setOnDragOver(e -&gt; {\r\n            if (e.getGestureSource() != textArea\r\n                    &amp;&amp; e.getDragboard().hasString()) {\r\n                e.acceptTransferModes(TransferMode.COPY_OR_MOVE);\r\n                TextAreaSkin textAreaSkin = (TextAreaSkin) textArea.getSkin();\r\n                HitInfo hitInfo = textAreaSkin.getIndex(e.getX(), e.getY() + textArea.scrollTopProperty().getValue());\r\n\/\/                int insertionPoint = hitInfo.getInsertionIndex(); \/\/ JavaFX 8\r\n\/\/                textArea.positionCaret(insertionPoint); \/\/ JavaFX 8\r\n                textAreaSkin.positionCaret(hitInfo, false); \/\/ JavaFX 9\r\n            }\r\n            e.consume();\r\n        });\r\n\r\n        textArea.setOnDragDropped(e -&gt; {\r\n            Dragboard dragboard = e.getDragboard();\r\n            boolean success = false;\r\n            if (dragboard.hasString()) {\r\n                textArea.insertText(textArea.getCaretPosition(), dragboard.getString());\r\n                success = true;\r\n            }\r\n            e.setDropCompleted(success);\r\n            e.consume();\r\n        });\r\n\r\n    }\r\n\r\n    \/**\r\n     * @param args the command line arguments\r\n     *\/\r\n    public static void main(String[] args) {\r\n        launch(args);\r\n    }\r\n\r\n    private void exceptionOccured(Exception ex) {\r\n        Alert alert = new Alert(Alert.AlertType.ERROR);\r\n\r\n        StringWriter sw = new StringWriter();\r\n        PrintWriter pw = new PrintWriter(sw);\r\n        ex.printStackTrace(pw);\r\n        pw.flush();\r\n        String stackTrace = sw.toString();\r\n\r\n        TextArea textArea = new TextArea(stackTrace);\r\n        textArea.setEditable(false);\r\n        alert.getDialogPane().setExpandableContent(textArea);\r\n        alert.initStyle(StageStyle.TRANSPARENT);\r\n\/\/            alert.setTitle(\"ERROR\");\r\n        alert.setHeaderText(\"Error!\\n\" + ex.getClass().getSimpleName());\r\n        alert.setContentText(\"Exit the application.\");\r\n        alert.showAndWait()\r\n                .filter(response -&gt; response == ButtonType.OK)\r\n                .ifPresent(response -&gt; {\r\n                    Platform.exit();\r\n                    System.exit(0);\r\n                });\r\n    }\r\n\r\n}\r\n\r\n<\/pre>\n<p>\u30d5\u30a9\u30f3\u30c8\u306f STARWARS.TTF \u30d5\u30a9\u30f3\u30c8\u3092\u4f7f\u3063\u3066\u307e\u3059\u3002\uff08\u4f55\u51e6\u3067\u5165\u624b\u3057\u3066\u304b\u5fd8\u308c\u307e\u3057\u305f\u3002\uff09<\/p>\n<p>\u9577\u304f\u30c0\u30e9\u30c0\u30e9\u3068\u3057\u305f\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u6700\u5f8c\u307e\u3067\u8aad\u3093\u3067\u304f\u3060\u3055\u3063\u3066\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\u3002<\/p>\n<p>\u9593\u9055\u3044\u304c\u3042\u308a\u307e\u3057\u305f\u3089\u30b3\u30e1\u30f3\u30c8\u3044\u305f\u3060\u3051\u308b\u3068\u3042\u308a\u304c\u305f\u3044\u3067\u3059\u3002<\/p>\n<p><a href=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/15.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" title=\"15\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"15\" src=\"http:\/\/yucchi.jp\/blog\/wp-content\/uploads\/2016\/12\/15_thumb.jpg\" width=\"892\" height=\"281\"><\/a><\/p>\n<div id=\"scid:0767317B-992E-4b12-91E0-4F059A8CECA8:cf6f7ae3-c4f8-4ddf-9336-0acecd67a9a3\" class=\"wlWriterEditableSmartContent\" style=\"float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px\">Hatena \u30bf\u30b0: <a href=\"http:\/\/b.hatena.ne.jp\/t\/Java\" rel=\"tag\">Java<\/a>,<a href=\"http:\/\/b.hatena.ne.jp\/t\/JavaFX\" rel=\"tag\">JavaFX<\/a><\/div>\n<div class='wp_social_bookmarking_light'>\n            <div class=\"wsbl_hatena\"><a href='\/\/b.hatena.ne.jp\/add?mode=confirm&url=http%3A%2F%2Fyucchi.jp%2Fblog%2F%3Fp%3D2282&title=HitInfo%E3%82%92%E5%B0%91%E3%81%97%E3%81%A0%E3%81%91%26hellip%3B' title='\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0' rel=nofollow class='wp_social_bookmarking_light_a' target=_blank><img src='http:\/\/yucchi.jp\/blog\/wp-content\/plugins\/wp-social-bookmarking-light\/public\/images\/hatena.gif' alt='\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0' title='\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0' width='16' height='12' class='wp_social_bookmarking_light_img' \/><\/a><\/div>\n            <div class=\"wsbl_facebook\"><a href='http:\/\/www.facebook.com\/share.php?u=http%3A%2F%2Fyucchi.jp%2Fblog%2F%3Fp%3D2282&t=HitInfo%E3%82%92%E5%B0%91%E3%81%97%E3%81%A0%E3%81%91%26hellip%3B' title='Facebook \u306b\u30b7\u30a7\u30a2' rel=nofollow class='wp_social_bookmarking_light_a' target=_blank><img src='http:\/\/yucchi.jp\/blog\/wp-content\/plugins\/wp-social-bookmarking-light\/public\/images\/facebook.png' alt='Facebook \u306b\u30b7\u30a7\u30a2' title='Facebook \u306b\u30b7\u30a7\u30a2' width='16' height='16' class='wp_social_bookmarking_light_img' \/><\/a><\/div>\n            <div class=\"wsbl_google_plus_one\"><g:plusone size=\"medium\" annotation=\"none\" href=\"http:\/\/yucchi.jp\/blog\/?p=2282\" ><\/g:plusone><\/div>\n            <div class=\"wsbl_twitter\"><a href=\"https:\/\/twitter.com\/share\" class=\"twitter-share-button\" data-url=\"http:\/\/yucchi.jp\/blog\/?p=2282\" data-text=\"HitInfo\u3092\u5c11\u3057\u3060\u3051&hellip;\" data-lang=\"ja\">Tweet<\/a><\/div>\n    <\/div>\n<br class='wp_social_bookmarking_light_clear' \/>\n","protected":false},"excerpt":{"rendered":"<p>\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u306f\u3001JavaFX Advent Calendar 2016 \u306e10\u65e5\u76ee\u3067\u3059\u3002 \u6628\u65e5\u306f @nodamushi \u3055\u3093\u306e\u300cJavaFX9\u304c\u826f\u3044\u611f\u3058\u306b\u306a\u3063\u3066\u304d\u305f\u4ef6\u300d\u3067\u3057\u305f\u3002 \u660e\u65e5\u306f @skrb \u3055\u3093\u306e\u300c\u4f55\u304b\u66f8\u304d\u307e\u3059\u300d\u3067\u3059\u3002 \u79c1\u306f\u82f1\u8a9e\u304c\u3088\u304f\u89e3\u3089\u306a\u3044\u306e\u30672015\u5e74\u306b\u3053\u3093\u306a\u3082\u306e\u3092\u4f5c\u308d\u3046\u3068\u3057\u307e\u3057\u305f\u3002(^_^; \u82f1\u6587\u30b5\u30a4\u30c8\u3092\u8aad\u307f\u8fbc\u3093\u3067\u30c6\u30ad\u30b9\u30c8\u5316\u3057\u3001\u82f1\u5358\u8a9e\u306e\u4e0a\u306b\u30de\u30a6\u30b9\u3092\u3042\u3066\u308b\u3068\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u3067\u65e5\u672c\u8a9e\u8a33\u3092\u8868\u793a\u3059\u308b\u3068\u3044\u3046\u5b89\u6613\u306a\u767a\u60f3\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u3059\u3002 https:\/\/www.youtube.com\/watch?v=JfifsvUVeKE \u4f5c\u3063\u3066\u308b\u9014\u4e2d\u3067\u3044\u304f\u3064\u304b\u306e\u554f\u984c\u306b\u906d\u9047\u3057\u307e\u3057\u305f\u3002 \u305d\u306e\u4e2d\u3067 JavaFX \u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[21],"class_list":["post-2282","post","type-post","status-publish","format-standard","hentry","category-javafx","tag-javafx"],"_links":{"self":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2282","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2282"}],"version-history":[{"count":1,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2282\/revisions"}],"predecessor-version":[{"id":2283,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2282\/revisions\/2283"}],"wp:attachment":[{"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2282"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/yucchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}