JavaFX 停止在 WebView 中打开 URL - 改为在浏览器中打开
我使用的嵌入式 WebView 浏览器需要对特定 URL 进行特殊处理,以便在本机默认浏览器而不是 WebView 中打开它们.实际的浏览部分工作正常,但我还需要阻止 WebView 显示该页面.我可以想到几种方法来做到这一点,但它们都不起作用.这是我的代码:
The embedded WebView browser I am using needs special handling for particular URLs, to open them in the native default browser instead of WebView. The actual browsing part works fine but I need to stop the WebView from displaying that page as well. I can think of several ways to do it but none of them work. Here is my code:
this.wv.getEngine().locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
{
Desktop d = Desktop.getDesktop();
try
{
URI address = new URI(observable.getValue());
if ((address.getQuery() + "").indexOf("_openmodal=true") > -1)
{
// wv.getEngine().load(oldValue); // 1
// wv.getEngine().getLoadWorker().cancel(); // 2
// wv.getEngine().executeScript("history.back()"); // 3
d.browse(address);
}
}
catch (IOException | URISyntaxException e)
{
displayError(e);
}
}
});
更多关于三种情况下发生的情况的信息
A bit more info about what happens in each of three cases
wv.getEngine().load(oldValue);
这会杀死 JVM.有趣的是,该页面在本机浏览器中可以正常打开.
This kills the JVM. Funnily enough, the page opens fine in the native browser.
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000005b8fef38, pid=7440, tid=8000
#
# JRE version: 7.0_09-b05
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [jfxwebkit.dll+0x2fef38] Java_com_sun_webpane_platform_BackForwardList_bflItemGetIcon+0x184f58
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:UsersGreg BalagaeclipseCompanyapphs_err_pid7440.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
2.取消工人
wv.getEngine().getLoadWorker().cancel();
什么都不做,页面在 WebView 和本机浏览器中加载.
Does nothing, the page loads in both the WebView and native browser.
wv.getEngine().executeScript("history.back()");
同上,没有效果.
我还尝试不查看 WebEngine
的 locationProperty
,而是在 Worker
的 stateProperty
的 chenges 上监听code> 并在 newState == State.SCHEDULD
时触发相同的开启代码.结果与以前的方法没有区别(除了实际上不能使用#1).
I have also tried to instead of looking the locationProperty
of WebEngine
, listen on chenges for stateProperty
of the Worker
and fire the same opening code if newState == State.SCHEDULED
. There was no difference in result from previous method (apart from not actually being able to use #1).
我现在使用的代码仍然会导致 JVM 崩溃:
The code I'm using now still crashes the JVM:
this.wv.getEngine().locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, final String oldValue, String newValue)
{
Desktop d = Desktop.getDesktop();
try
{
URI address = new URI(newValue);
if ((address.getQuery() + "").indexOf("_openmodal=true") > -1)
{
Platform.runLater(new Runnable() {
@Override
public void run()
{
wv.getEngine().load(oldValue);
}
});
d.browse(address);
}
}
catch (IOException | URISyntaxException e)
{
displayError(e);
}
}
});
<小时>
解决方法
好的,我设法通过拆除 webview 并重建它来使其工作.
Workaround
Ok I managed to make it work by tearing down the webview and rebuilding it.
this.wv.getEngine().locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, final String oldValue, String newValue)
{
Desktop d = Desktop.getDesktop();
try
{
URI address = new URI(newValue);
if ((address.getQuery() + "").indexOf("_openmodal=true") > -1)
{
Platform.runLater(new Runnable() {
@Override
public void run()
{
grid_layout.getChildren().remove(wv);
wv = new WebView();
grid_layout.add(wv, 0, 1);
wv.getEngine().load(oldValue);
}
});
d.browse(address);
}
}
catch (IOException | URISyntaxException e)
{
displayError(e);
}
}
});
推荐答案
还有另一种处理方法.
您可以向 DOM 元素添加事件侦听器并以这种方式拦截它.
You can add an event listener to the DOM elements and intercept it that way.
例子:
NodeList nodeList = document.getElementsByTagName("a");
for (int i = 0; i < nodeList.getLength(); i++)
{
Node node= nodeList.item(i);
EventTarget eventTarget = (EventTarget) node;
eventTarget.addEventListener("click", new EventListener()
{
@Override
public void handleEvent(Event evt)
{
EventTarget target = evt.getCurrentTarget();
HTMLAnchorElement anchorElement = (HTMLAnchorElement) target;
String href = anchorElement.getHref();
//handle opening URL outside JavaFX WebView
System.out.println(href);
evt.preventDefault();
}
}, false);
}
其中 document 是 DOM 文档对象.确保在文档加载完成后完成此操作.
Where document is the DOM document object. Make sure this is done after the document has finished loading.
相关文章