JavaFX HTMLEditor文本更改侦听器

JavaFX HTMLEditor文本更改侦听器,java,javafx,javafx-2,Java,Javafx,Javafx 2,我对JavaFX世界相当陌生,似乎不知道如何在HTMLEditor组件中侦听文本修改事件 我需要这个,因为我正在将这个小部件连接到一个需要更新的模型 addEventFilterAPI,带有KeyEvent.KEY\u-TYPED事件类型,似乎无法正常工作。调用其处理程序时,getHTMLText()尚未使用最新字符进行更新(如果有人不理解此段落,我将提供一个分步示例) TextField有一个textProperty(),可以在其上附加侦听器 那么HTMLEditor呢 另外,最好只在文本修改

我对JavaFX世界相当陌生,似乎不知道如何在HTMLEditor组件中侦听文本修改事件

我需要这个,因为我正在将这个小部件连接到一个需要更新的模型

addEventFilter
API,带有
KeyEvent.KEY\u-TYPED
事件类型,似乎无法正常工作。调用其处理程序时,
getHTMLText()
尚未使用最新字符进行更新(如果有人不理解此段落,我将提供一个分步示例)

TextField有一个
textProperty()
,可以在其上附加侦听器
那么HTMLEditor呢


另外,最好只在文本修改事件中调用侦听器(例如,不要在CTRL+A上调用)。你知道的。。。像SWT Text的
addModifyListener()

一样,在我的一个项目应用程序中使用JavaFX
HTMLEditor
时,我也遇到了类似的情况。最后,我添加了一个
按钮
,单击该按钮可以解析HTML文本,并执行进一步的任务。通过
AnchorPane
,我可以无缝地在HTMLEditor上添加
按钮,它看起来就像它的一部分

不管怎样,这里有一个小例子,告诉你如何在没有任何额外按钮的情况下实现你想要的:

package application;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;

public class Main extends Application
{
  @Override
  public void start(Stage primaryStage)
  {
    try
    {
      final HTMLEditor editor = new HTMLEditor();
      Scene scene = new Scene(editor);
      primaryStage.setScene(scene);

      editor.setOnKeyReleased(new EventHandler<KeyEvent>()
      {
        @Override
        public void handle(KeyEvent event)
        {
          if (isValidEvent(event))
          {
            System.out.println(editor.getHtmlText());
          }
        }

        private boolean isValidEvent(KeyEvent event)
        {
          return !isSelectAllEvent(event)
              && ((isPasteEvent(event)) || isCharacterKeyReleased(event));
        }

        private boolean isSelectAllEvent(KeyEvent event)
        {
          return event.isShortcutDown() && event.getCode() == KeyCode.A;
        }

        private boolean isPasteEvent(KeyEvent event)
        {
          return event.isShortcutDown() && event.getCode() == KeyCode.V;
        }

        private boolean isCharacterKeyReleased(KeyEvent event)
        {
          // Make custom changes here..
          switch (event.getCode())
          {
            case ALT:
            case COMMAND:
            case CONTROL:
            case SHIFT:
              return false;
            default:
              return true;
          }
        }
      });

      primaryStage.show();
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    launch(args);
  }
}
包应用;
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.input.KeyCode;
导入javafx.scene.input.KeyEvent;
导入javafx.scene.web.HTMLEditor;
导入javafx.stage.stage;
公共类主扩展应用程序
{
@凌驾
公共无效开始(阶段primaryStage)
{
尝试
{
最终HTMLEditor编辑器=新HTMLEditor();
场景=新场景(编辑器);
初级阶段。场景(场景);
setOnKeyReleased(新的EventHandler()
{
@凌驾
公共无效句柄(KeyEvent事件)
{
如果(是有效的(事件))
{
System.out.println(editor.getHtmlText());
}
}
私有布尔值isValidEvent(KeyEvent事件)
{
return!IsSelectalEvent(事件)
&&((isPasteEvent(事件))| | isCharacterKeyReleased(事件));
}
私有布尔IsSelectalEvent(KeyEvent事件)
{
返回event.isShortcutDown()&&event.getCode()==KeyCode.A;
}
私有布尔值isPasteEvent(KeyEvent事件)
{
返回event.isShortcutDown()&&event.getCode()==KeyCode.V;
}
私有布尔值isCharacterKeyReleased(KeyEvent事件)
{
//在此处进行自定义更改。。
开关(event.getCode())
{
案例备选:
案例命令:
病例对照:
案例转移:
返回false;
违约:
返回true;
}
}
});
primaryStage.show();
}
捕获(例外e)
{
e、 printStackTrace();
}
}
公共静态void main(字符串[]args)
{
发射(args);
}
}
更新: 经过一番思考,我找到了一种方法来完成事件处理,即使是点击按钮。以下是方法:

EventHandler<MouseEvent> onMouseExitedHandler = new EventHandler<MouseEvent>()
{
  @Override
  public void handle(MouseEvent event)
  {
    System.out.println(editor.getHtmlText());
  }
};

for (Node node : editor.lookupAll("ToolBar"))
{
  node.setOnMouseExited(onMouseExitedHandler);
}
EventHandler onMouseExitedHandler=新的EventHandler()
{
@凌驾
公共无效句柄(MouseeEvent事件)
{
System.out.println(editor.getHtmlText());
}
};
for(节点:editor.lookupAll(“工具栏”))
{
setOnMouseExited(onMouseExitedHandler);
}
如果您看到
HTMLEditor
,它有两个
工具栏

我在代码中所做的是
查找这两个工具栏的
,并设置
onMouseExited
事件处理程序。类似的情况是,如果用户输入HTML文本并对其进行一些更改,然后退出工具栏,则会触发一个事件,然后可以处理该事件

您甚至可以根据需要在这两个工具栏上设置不同类型的事件处理程序,但在我看来,这些
onMouseExited
事件处理程序在与
onKeyReleased
事件处理程序一起使用时提供了非常广泛的覆盖范围。不过,基于mouseexited处理程序的覆盖范围并不准确。

这里是一个简单的覆盖范围

public class HtmlEditorListener {
    private final BooleanProperty editedProperty;

    private String htmlRef;

    public HtmlEditorListener(final HTMLEditor editor) {
        editedProperty = new SimpleBooleanProperty();
        editedProperty.addListener((ov, o, n) -> htmlRef = n? null: editor.getHtmlText());
        editedProperty.set(false);

        editor.setOnMouseClicked(e -> checkEdition(editor.getHtmlText()));
        editor.addEventFilter(KeyEvent.KEY_TYPED, e -> checkEdition(editor.getHtmlText()));
    }

    public BooleanProperty editedProperty() {
        return editedProperty;
    }

    private void checkEdition(final String html) {
        if (editedProperty.get()) {
            return;
        }
        editedProperty.set(htmlRef != null
                && html.length() != htmlRef.length()
                || !html.equals(htmlRef));
    }
}

HtmlEditor基于Web视图

    HTMLEditor editor = getEditor();
    WebView webView = (WebView) getEditor().lookup("WebView");
    new WebViewEditorListener(webView, new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {

        }
    });
HTMLEditor editor=getEditor();
WebView WebView=(WebView)getEditor().lookup(“WebView”);
新建WebViewEditorListener(webView,新建ChangeListener(){
@凌驾

公共作废已更改(复制粘贴如何?:-(@GGrec:我已经更新了答案,以便对剪切和粘贴事件做出反应,我相信你足够聪明,可以根据自己的需要配置这个低级键侦听器。哦,伙计,这是显而易见的。我将抛出另一个快速问题,因为它在同一页上。HTML的更改如何?例如,用鼠标选择一些文本,然后更改为粗体。The模型应该更改,但它不是类型事件。@GGrec:必须说这是一个很棒的问题。显然,您在HTML编辑器中看到的所有按钮和工具栏都是
HTMLEditorSkin
类的一部分,并且这些按钮都声明为私有,因此无法访问它们。在这种情况下,我要做的就是构建一个自定义HTML e从头开始编辑,复制粘贴
HTMLEditor
和相关类的JavaFX源代码,然后对其进行适当调整。我会采取的第二种方法是在另一个线程上运行计时器服务,每隔几秒钟检索HTML文本并相应地解析它。
public static class WebViewEditorListener {

        private final ChangeListener<String> listener;

        private final WebPage webPage;

        private String htmlRef, innerText;

        public WebViewEditorListener(final WebView editor, ChangeListener<String> listener) {
            this.listener = listener;
            webPage = Accessor.getPageFor(editor.getEngine());

            editor.setOnMouseClicked(e -> onKeyTyped(webPage.getHtml(webPage.getMainFrame())));
            editor.addEventFilter(KeyEvent.KEY_TYPED, e -> onKeyTyped(webPage.getHtml(webPage.getMainFrame())));
        }

        public String getHtmlContent(){
            return htmlRef == null ? "" : htmlRef ;
        }

        private void onKeyTyped(final String html) {
            boolean isEqual = htmlRef != null ? htmlRef.length() == html.length() : html == null;
            if (!isEqual){
                String text = webPage.getInnerText(webPage.getMainFrame());
                listener.changed(null, innerText, text);
                innerText = text;
                htmlRef = html;
            }

        }
    }