I have a piece of code in JavaFX which creates a small web browser. The web page is shown in a web view. I have managed to get custom context menu popped up by right clicking on the links on the webpage. The context menu has a menu item labeled "open in new tab". However, I have a strange problem. If I click on the "open in new tab", sometimes related webpage opens in new tab, but other times it fails to do so. Please note that if I implement the functionality without any context menu and using right click alone directly on the link, the link opens every time in new tab. How do we describe the situation? Is it a threading issue? I have tested the code on Windows 7 64-bit and Windows 8.1 64-bit. I am using BlueJ on Java 17 and JavaFX 20.
import javafx.application.Application; import javafx.application.Platform; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.scene.web.WebEvent; import javafx.stage.Stage; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.event.EventHandler; import javafx.event.ActionEvent; public class QuickTab extends Application { TabPane tpane; TextField urlField; WebView webView; String url; public void start(Stage stage) { tpane = new TabPane(); Tab urlTab = new Tab(); HBox box = new HBox(); urlField = new TextField(); urlField.setPromptText("Enter URL"); Button goBtn = new Button("Go"); goBtn.setOnAction(e -> load_page()); box.getChildren().addAll(urlField, goBtn); urlTab.setGraphic(box); tpane.getTabs().add(urlTab); stage.setScene(new Scene(tpane, 400, 300)); stage.show(); } private void load_page() { webView = new WebView(); WebEngine engine = webView.getEngine(); webView.setContextMenuEnabled(false);//*** Tab tab = new Tab("home tab"); tab.setContent(webView); tpane.getTabs().add(tab); engine.setOnStatusChanged((WebEvent<String> event) -> { url = event.getData(); }); engine.load(urlField.getText()); webView.setOnMouseClicked(new TabOpener()); } private class TabOpener implements EventHandler<MouseEvent> { public void handle(MouseEvent e) { if(e.getButton() == MouseButton.SECONDARY) { ContextMenu cmenu = new ContextMenu(); MenuItem item = new MenuItem("open in new tab"); cmenu.getItems().addAll(item); cmenu.show(webView, e.getScreenX(), e.getScreenY()); item.setOnAction(event -> { Platform.runLater(() -> load_newPage()); }); } e.consume(); } private void load_newPage() { WebView newView = new WebView(); WebEngine newEngine = newView.getEngine(); Tab newTab = new Tab(url); tpane.getTabs().add(newTab); newTab.setContent(newView); newEngine.load(url); } } }