是否可以在JavaFX中的自由流动文本中添加链接?

时间:2018-02-24 08:55:10

标签: java javafx text hyperlink

我正在使用标签来解释有关我的应用程序的一些长文本,并且我希望这些单词中的一些是可以触发事物的链接。有没有办法在JavaFX上做到这一点?

我知道Hyperlink元素,但这不是我想要的。我只希望文本的一部分是一个链接,而不是全部。

1 个答案:

答案 0 :(得分:2)

一些选项:

  1. Hyperlink中使用TextTextFlow个元素。这需要一些工作才能使其具备生产质量。
  2. 使用RichTextFX,它允许您通过CSS设置单个文本元素的样式,还允许您在鼠标事件中获取字符索引。
  3. 为您的文字使用HTML并将其显示在WebView中。如果您希望链接仅仅作为链接工作,那么它将开箱即用;如果您希望更好地控制对它们的处理事件,您也可以使用Javascript回调JavaFX应用程序。
  4. 选项1和3的演示是:

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Hyperlink;
    import javafx.scene.control.ScrollPane;
    import javafx.scene.layout.Priority;
    import javafx.scene.layout.VBox;
    import javafx.scene.text.Text;
    import javafx.scene.text.TextFlow;
    import javafx.scene.web.WebEngine;
    import javafx.scene.web.WebView;
    import javafx.stage.Stage;
    import netscape.javascript.JSObject;
    
    public class TextFlowHyperlinkTest extends Application {
    
    
        private final static String TEXT = 
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
                + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
                + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris "
                + "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
                + "reprehenderit in voluptate velit esse cillum dolore eu "
                + "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
                + "sunt in culpa qui officia deserunt mollit anim id est laborum." ;
    
        @Override
        public void start(Stage primaryStage) {
            TextFlow textFlow = new TextFlow();
    
            for (String word : TEXT.split("\\s")) {
                // arbitraily make some words hyperlinks:
                if (word.length() == 6) {
                    Hyperlink hyperlink = new Hyperlink(word);
                    hyperlink.setOnAction(e -> System.out.println("Click on "+word));
                    textFlow.getChildren().add(hyperlink);
                } else {
                    textFlow.getChildren().add(new Text(word+" "));
                }
            }
    
            ScrollPane textFlowScroller = new ScrollPane(textFlow);
            textFlowScroller.setFitToWidth(true);
            textFlowScroller.setMinHeight(200);
            VBox.setVgrow(textFlowScroller, Priority.ALWAYS);
    
            WebView webView = new WebView();
            WebEngine engine = webView.getEngine();
            engine.documentProperty().addListener((obs, oldDoc, newDoc) -> {
                if (newDoc != null) {
                    JSObject window = (JSObject) engine.executeScript("window");
                    window.setMember("app", this);
                }
            });
            StringBuilder html = new StringBuilder();
            html.append("<html><body><div name='text'>");
            for (String word : TEXT.split("\\s")) {
                if (word.length() == 6) {
                    html.append("<a href='#' onclick='app.process(\""+word+"\")'>")
                        .append(word).append("</a> ");
                } else {
                    html.append(word).append(" ");
                }
            }
            html.append("</div></body></html>");
            engine.loadContent(html.toString());
    
            VBox.setVgrow(webView, Priority.ALWAYS);
    
    
            Scene scene = new Scene(new VBox(10, textFlowScroller, webView), 400, 600);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public void process(String text) {
            System.out.println("Click on "+text);
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }