When using a JavaFX (2.2) WebView, is there a way to listen to and handle url's within java code?
For example: I'm loading a local HTML file to my WebView with webEngine.loadContent(html). The HTML contains resources like
<script src="local:my-script.js"></script>
<img src="cms:1234.png"/>
which is also a local file and should be provided from the java application. So I want to register a listener that could handle requests from the page.
Edit: The resource data that is loaded within the HTML page comes from a content-managemant-system so using relative paths is not working.
Create your own URL protocol handler and install it using:
URL.setURLStreamHandlerFactory(new HandlerFactory());
A New Era for Java URL Protocol Handlers article provides detailed instructions for creating the handler.
WebView can make use of your custom protocol to load your content.
The easiest way for you would be substituting local: resource with runtime value in html right before loading it. E.g.:
public class WebViewLocal extends Application {
#Override
public void start(Stage primaryStage) {
String st = "<html><head><title>X</title>"
+ "</head><body><img src='local:1.jpg'/>"
+ "</body></html>";
System.out.println(st);
primaryStage.setScene(new Scene(loadHtml(st), 400, 400));
primaryStage.show();
}
public WebView loadHtml(String html) {
html = html.replace("local:", getClass().getResource(".").toString());
WebView view = new WebView();
view.getEngine().loadContent(html);
return view;
}
public static void main(String[] args) { launch(); }
}
N.B.: This is working sample, just put 1.jpg image at the same place as this file.
If you really want to work with java class from javascript you can use "JavaFX to JavaScript bridge" feature. Take a look at tutorial here: https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx
If you load your html-file locally, you can simply use relative paths:
This is an example, which load html, with relative scripts.
http://code.google.com/p/jfx-gap/source/browse/src/main/java/com/googlecode/jfxgap/JFXGap.java
The trick schould be the relative path inside the html.
Related
I am trying to make a code editor using JavaFX and want to use Ace. I saw an earlier post that used WebView to achieve this but I am a little lost on how to set up my project structure beforehand.
The following is a very minimal implementation with JavaFX's WebView and the Ace editor.
To get started, I'll just use a few required js files from the Ace repository:
editor.html, this is the main entry. Download from here, and add it to the resources folder, like: src/main/resources/ace/editor.html.
mode-java.js, download from here, and add it to resources: src/main/resources/ace/js/mode-java.js.
theme-eclipse.js, download from here, and add it to resources: src/main/resources/ace/js/theme-eclipse.js.
Note that the above project structure corresponds with the use of Maven or Gradle build tools. To get started, I used this project as a reference.
Now edit the editor.html file, and replace the existing scripts with:
<script src="js/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var editor = ace.edit("editor");
editor.setTheme("ace/theme/eclipse");
editor.session.setMode("ace/mode/java");
</script>
Optionally, replace the javascript function with some java code, like:
<pre id="editor">package com.ace.editor;
import java.util.ArrayList;
public class AceEditor {
/*
* This is a demo
*/
public static void main(String[] args) {
System.out.println("Hello World");
}
}</pre>
Finally, in your JavaFX code, add a WebView control, and load the editor:
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.load(getClass().getResource("/ace/editor.html").toExternalForm());
Scene scene = new Scene(webView, 600, 400);
...
Note that you will need to add the javafx.web module. This is using Gradle, but the same could be done with Maven.
javafx {
version = "13"
modules = [ 'javafx.web' ]
}
Build and run the project, and you should get the code editor:
More functionality can be added by modifying the editor.html file, and adding more js files, to extend the editor options. For instance, this shows you can add a statusbar.
EDIT
This is my project structure:
(It uses FXML as well, but doesn't change anything of the above).
I am using netbeans. I have a project directory like this:
HTMLEdit/
src/
htmledit/
- pic.png
- MyClass.java
I tried to get the image, but it return null. I had trying both of these but still cannot get it to work:
System.out.println(getClass().getResourceAsStream("/pic.png"));
and
System.out.println(getClass().getResourceAsStream("pic.png"));
What's causing this weird behavior?
EDIT :
It looks like it's because I choosed JAVAFX Project when created the project. I recreate the project by choosing Java Project and it works fine. May be this is Netbeans bug.
getClass().getResourceAsStream() is used for files embedded inside your java jar file. You should use FileInputStream if you need to read a file from your file system as a stream of bytes. Here's the documentation: https://docs.oracle.com/javase/8/docs/api/java/io/FileInputStream.html
When you do getClass().getResourceAsStream("/pic.png")then the url that will be looked to access the file will be an absolute url. The absolute URL is indicated by the slash which is at the front of the resource location.
If you do getClass().getResourceAsStream("pic.png"), then a resource relative to the package where the class resides will be used.
Because you said that both of the getResourceAsStream() statements did not work in Netbeans, I checked the below JavaFX code in Netbeans and it worked perfectly.
public class MyClass extends Application{
#Override
public void start(Stage primaryStage) {
Pane root = new Pane();
Image images = new Image(getClass().getResourceAsStream("pic.png"));
ImageView image = new javafx.scene.image.ImageView(images);
root.getChildren().add(image);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Here is the structure and the output of the program.
In case if you want to know the Netbeans version, I am using then it is Netbeans 8.0.2.
Also, read the following post.
Different ways of loading a file as an InputStream
I have a PDF file stored in server and I want to display it on the client side. How can I make the pdf displayed in the required place?
You can create a frame widget with a reference to your PDF file. The Frame widget in GWT will render an HTML iFrame in your browser.
public class FrameExample implements EntryPoint {
public void onModuleLoad() {
// Make a new frame, and point it at Google.
Frame frame = new Frame("http://www.mydomain.com/path to my pdf");
// Add it to the root panel. or anywhere you want
RootPanel.get().add(frame);
}
}
I have used following. Its working fine. May be its usefull for you.
GWT Client side:
HTML pdf = new HTML("<embed src='http://www.mydomain.com/path to my pdf' width='100%' height='500px'></embed>");
PDFPannel.add(pdf);
I have some queries when trying to implement a fileupload widget in my application. After many tries, it just doesn't seem to work.
Hence, I tried getting working solutions to see if I can understand anything from there.
http://code.google.com/p/faculty-gwt/source/checkout
However, I tried uploading a file using this and it seems that I am getting error messages too. and what is that textbox and listbox suppose to do? It is meant for showing an example of validating an input before submitting?
Can someone guide me along to solve this? Thanks.
Never tried to use the link you provided, but this is what i did to use a a GWT FileUpload widget:
I built a File Upload widget using the uibinder:
<g:FormPanel ui:field="docForm">
<g:FlowPanel ui:field="inputPane">
/*other displayed info*/
<g:FileUpload ui:field="DocPath"/>
/*other displayed info*/
</g:FlowPanel>
</g:FormPanel>
(Per the GWT api, FileUpload widgets can only be used from a FormPanel)
Make sure you set these in the FormPanel, otherwise you'll probably have issues:
yourFormPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
yourFormPanel.setMethod(FormPanel.METHOD_POST);
That widget is dropped into my container page, then added to the display panel:
private FileUploadWidget createNewUploader(){
FileUploadWidget uploader = new FileUploadWidget(/*my constructor params*/);
uploader.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent event) {
DocPanel.add(createNewUploader());
}
});
return uploader;
}
My OnChange event is so that I have a new, blank uploader available when i use the current one.
and when I'm ready to submit:
private void processUpload(FileUploadWidget upload, int id) {
upload.setId(id);
//Don't bother to submit an empty one.
if (upload.IsFileSelected())
upload.Submit();
}
I have created a JApplet using the JUNG library in Netbeans that compiles and runs normally. However, when I try to create an html file that runs the applet, only a grey pane appears but the components are missing.
My class is :
public class View extends JApplet {
//Here I declare the buttons etc..
public View()
{
initializeComponent();
fetchGraphs();
}
public static void main(String[] args) throws IOException{
f = new JFrame();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
x = screenSize.width;
y = screenSize.height;
f.getContentPane().add(new View());
f.setTitle("Social Network Privacy Settings and Access Control");
f.setLocation(new Point(15, 20));
f.setSize(new Dimension(x-20,y-50));
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setResizable(false);
f.setVisible(true);
}
}
The method initializeComponent() adds all the components to the main window. I used JFrameBuilder to build some basic components. JFrameBuilder uses a method addComponent(container, component, x, y, width, height) to add components
I use the code below for that:
contentPane = (JPanel)this.getContentPane();
//to create the japplet contentpane
addComponent(contentPane, genGraphButton, (int)(0.35*x),(int)(0.63*y),
(int)(0.2*x),28);
// to add components
Then I create an html file:
<applet code = 'MyPackage.View'
archive = 'MyProject.jar',
width = 1600,
height = 800/>
in the /dist folder but then only a grey pane appears when I try to open it with Mozilla Firefox. The strange thing is that I have created another simple applet, this time with netbeans JBuilder and it runs normally in a web page.
I really need some help!
You mention the JUNG library, it relies on the two third party libraries, Collections-Generic & Cern Colt Scientific Library 1.2.0. As mentioned by #othman they need to be added to the run-time class-path of the applet (added to the archive attribute of the applet element).
But just so we are clear, make sure the HTML contains more than just the applet element. Something like this:
<html>
<body>
<applet
code='MyPackage.View'
archive='MyProject.jar,jung.jar,collections.jar,colt-scientific.jar'
alt='Java is DISABLED in this browser!'
width='1600'
height='800'>
This browser does not recognize the applet element!
</applet>
</body>
</html>
Of course, you'll need to change the names of the last 3 Jars to their real names.
I'm no Applet expert, since I don't use them, but IIRC you need the init() method to initialize your view. main(...) is not called for an applet.
First, I am not sure that new lines you added into the html are legal. I mean write <applet and /> without any new lines and spaces.
Second, test that your jar is really available. To do this go to the same URL that you go to retrieve your HTML without HTML but with jar, i.e.
if your HTML URL is: http://somehost/my.html type in browser http://somehost/MyProject.jar and see that you can download the jar.
if this works check the code attribute. Is your package name really MyPackage? Capitalized? Do you know it is not according the naming convention?
Also check java console. Find it somewhere in menus of your browser: it depends in browser. I believe that you will see the reason there in form of exception stack trace.
you need to reference also the JUG jars in your applet tag :
<
applet code = 'MyPackage.View'
archive = 'MyProject.jar , jung_xx.jar',
width = 1600,
height = 800 /
>
in the archive attribute add all jung jars that you have currently in your netbeans project classpath.