Christopher has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

DJ NativeSwing - reloaded: JWebBrowser, JFlashPlayer, JVLCPlayer, JHTMLEditor.

03.12.2008
| 45484 views |
  • submit to reddit

Today's release of DJ Native Swing 0.9.4 greatly improves stability and brings new components: in addition to the JWebBrowser and JFlashPlayer, there is now the JVLCPlayer and the JHTMLEditor.
Here is a summary of what to expect when using this library.

 

1. Various native components

DJ Native Swing was designed to handle all the complexity of native integration, mainly in the form of components with a simple Swing-like API.

Here are some screenshots of several components in action (click to enlarge):

JWebBrowser:
JFlashPlayer:
JWebBrowser JFlashPlayer
JVLCPlayer:
JHTMLEditor:
JVLCPlayer JHTMLEditor

 

2. Simple API

First, we need to initialize the framework. This needs to happen before any feature is used. A common place for this call is the first line of the main():

public static void main(String[] args) {
NativeInterfaceHandler.init();
// Here goes the rest of the initialization.
}

Now, let's see how to create a JWebBrowser, with its URL set to Google's homepage:

JWebBrowser webBrowser = new JWebBrowser();
webBrowser.setURL("http://www.google.com");
myContentPane.add(webBrowser);

Note that we set a URL, but we could as well set the HTML text. The JWebBrowser also allows to execute Javascript calls, and we can even propagate notifications from custom pages to our Swing application.

Moving to a more practical example, we may want to be notified of URL change events or track window opening events, potentially preventing navigation to occur or open the page elsewhere. This is easily achieved by attaching a listener:

webBrowser.addWebBrowserListener(new WebBrowserAdapter() {
public void urlChanging(WebBrowserNavigationEvent e) {
String newURL = e.getNewURL();
if(newURL.startsWith("http://www.microsoft.com/")) {
// Prevent the navigation to happen.
e.consume();
} else {
// We can consume the event and decide to open this page in a tab.
}
}
public void windowWillOpen(WebBrowserWindowWillOpenEvent e) {
// We can prevent, add the URL to a tab, etc.
}
// There are of course more events that can be received.
});

Let's have a look at the JFlashPlayer:

JFlashPlayer flashPlayer = new JFlashPlayer();
flashPlayer.setURL(myFlashURL);

The JFlashPlayer can open local or remote Flash files, and files from the classpath; the latter being a general capability of the library by proxying files using a minimalistic web server.
Of course, the JFlashPlayer allows to retrieve and set Flash variables, and play/pause/stop the execution.

The JVLCPlayer and the JHTMLEditor are no exceptions to this simplicity: playlist can be manipulated in the VLC player, HTML can be set and retrieved from the HTML editor, etc.

There is also the possibility to integrate Ole controls on Windows, still with a simple Swing-like API. An example is provided in the library in the form of an embedded Windows Media Player.

References
Published at DZone with permission of its author, Christopher Deckers. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Andrew McVeigh replied on Wed, 2008/03/12 - 8:45am

wow, really good stuff!  just a couple of questions / comments:

1. i notice the sourceforge page says win2k, winxp for the OS.  however, the flash, browser, html editor and (presumably) movie player work fine under my installation of ubuntu linux.  what exactly are the supported platforms?  if only windows, could you potentially expand the list based on the linux results?

 (i'm still investigating why this should be so (!), particularly as the download looks only to have the swt file for windows included.  i must have a reference to the SWT jars in my path or something like that?!)

2. might be an idea to put a more prominent link to the sourceforge summary page in the home page.  took me a while to find it.

Cheers,
Andrew 

Jeff Stano replied on Wed, 2008/03/12 - 8:49am

Wow, just what I was looking for. I'm also looking to integrate Adobe Acrobat Reader in. If you point me in the right direction I can assist in doing the work.

Andrew McVeigh replied on Wed, 2008/03/12 - 9:03am in response to: Andrew McVeigh

(i'm still investigating why this should be so (!), particularly as the download looks only to have the swt file for windows included. i must have a reference to the SWT jars in my path or something like that?!)

 err, whoops.  i just read your page which states it works on linux if xulrunner is installed.

Cheers,
Andrew 

 

Christopher Deckers replied on Wed, 2008/03/12 - 9:07am in response to: Andrew McVeigh

Andrew, 

1. Supported platforms include Windows, Linux, and potentially other platforms where SWT is supported and allows to integrate SWT components in Swing.

Linux was missing because this summary was for DJ Project - Native Integration, which is the first project that I did which was part of the DJ Project. I just added Linux to follow your suggestion. Thanks! 

About the SWT library, the download distribution is already quite big, so I decided to only ship the SWT library for Windows. For Linux, I explain in the readme file to simply place "swt.jar" in the classpath (by default the library looks up for "swt.jar" and falls back to the Windows version).

2. I will see if I should place another Sourceforge Link, or make it more visible.

Thanks a lot for your comments! 

-Christopher

 

Christopher Deckers replied on Wed, 2008/03/12 - 9:12am in response to: Jeff Stano

Jeff,

The Acrobat reader is a great idea! 

Impementation-wise, there are two possibilities:

  1. browser-based, piloted by Javascript (like the Flash player and the VLC player), so you could look into those sources.
  2. Win32 only by using Ole integration (in which case, the Window media player is a good example, but I aslo have a really simple JRealMedia component which is not part of the distribution).

I tend to favor browser-based component whenever possible, because it is cross-platform and handles all the plugin resolution problems.

Feel free to contact me via e-mail if you want to discuss it further.

Thanks!

-Christopher 

Christopher Deckers replied on Wed, 2008/03/12 - 3:32pm in response to: Jeff Stano

Jeff,

I investigated the browser-based approach to the PDF reader, and I have a few conclusions:

  • There are only few methods to act on the plugin that are interesting (show/hide toolbar, set zoom level).
  • These few methods only seem to work when the browser is IE.

Based on these findings, I believe it is not worth creating a new component (JPDFReader or whatever), but achieve the same result with:

JWebBrowser webBrowser = new JWebBrowser();
webBrowser.setBarsVisible(false);
webBrowser.setURL(pdfPathOrURL);

 

-Christopher

Jeff Stano replied on Wed, 2008/03/12 - 8:15pm

Great, I'll give it a try.

Wong Qil replied on Thu, 2008/03/13 - 1:45am in response to: Christopher Deckers

Actually, most MicroSoft office documents(Word, PowerPoint...) will work too, I mean, in IE.

[quote=chrriis]

Jeff,

I investigated the browser-based approach to the PDF reader, and I have a few conclusions:

  • There are only few methods to act on the plugin that are interesting (show/hide toolbar, set zoom level).
  • These few methods only seem to work when the browser is IE.

Based on these findings, I believe it is not worth creating a new component (JPDFReader or whatever), but achieve the same result with:

JWebBrowser webBrowser = new JWebBrowser();
webBrowser.setBarsVisible(false);
webBrowser.setURL(pdfPathOrURL);

 

-Christopher

[/quote]

Rob Blanchard replied on Mon, 2008/03/24 - 2:40pm

I didn't immediately see it, but does JWebBrowser provide any visiblity into reading or writing of cookies, or is that handled by a lower level object?

 This is great work... 0.9.4 is much more stable than previous versions.

Christopher Deckers replied on Mon, 2008/03/24 - 2:59pm in response to: Rob Blanchard

0.9.4 uses a completely different architecture, which was the only way to achieve stability.

About the cookies, it is all handled internally by the Internet Explorer / XULRunner engine, so this is not accessible. On-the-other hand, it is possible to clear all the session cookies of all instances.

 

Rob Blanchard replied on Tue, 2008/03/25 - 9:25pm

What is the proper invocation of the executeAndWaitForCommandResult method that is in the JWebBrowser class?  My motive is that it may be possible to retrieve cookie values by executing JavaScript to assign the document.cookie to a variable.  The return of this assignment should actually be the value of the variable (in other words, the cookies).

 Thanks for any assistance.

Christopher Deckers replied on Wed, 2008/03/26 - 2:06am in response to: Rob Blanchard

executeAndWaitForCommandResult executes some JS code, and expects that code to use the command channel to message back the result.

The API of that particular call has changed between 0.9.4 and the next 0.9.5, so if you want to use the latest version, please contact me by e-mail and I would give you a preview of the 0.9.5 version.

In 0.9.4, you would do something like:

String result = browser.executeAndWaitForCommandResult("getCookies", "sendCommand('getCookies:' + [JS GetCookie code]);");

In 0.9.5, sendCommand accepts parameters. Thus the call becomes:

String result = browser.executeAndWaitForCommandResult("getCookies", "sendCommand('getCookies', [JS GetCookie code]);");

Note that this method can only return a String result.

Don't hesitate to contact me by e-mail in case you have any other questions.

aslan ozturk replied on Sun, 2008/06/08 - 8:52am

Hi all

executeAndWaitForCommandResult executes some JS code, and expects that code to use the command channel to message back the result.

The API of that particular call has changed between 0.9.4 and the next 0.9.5, so if you want to use the latest version, please contact me by e-mail and I would give you a preview of the 0.9.5 version.

ankara evden eve nakliyat 

 

Christopher Deckers replied on Sun, 2008/06/08 - 1:28pm in response to: aslan ozturk

Indeed, I changed the API to make it much simpler.

Before, you had to execute a script that explicitely sends a message using the commnand channel, which meant you had to add a command listener.

Now you have a method that is synchronous and returns the result, without the need to explicitely send a command:
Object JWebBrowser.executeJavascriptWithResult(String javascript).

I believe this is a much cleaner API, that does not ressemble a hack as it was before :)

-Christopher

Keki Bakshi replied on Tue, 2008/06/24 - 12:31am

I want to use DJ Project - Native Swing... to load JFlashPlayer component so that I can run my flex code in a desktop application.

This Swing application is supported on Solaris. Does DJ Project - Native Swing library support Solaris platform? If no, then are there any plans to add support for solaris? 

 

ramesh kancherla replied on Wed, 2008/07/02 - 11:56am in response to: Wong Qil

Hi Chrriis,

           This is rameshkancherla. I am using DJ Native Swing Project. when i am sending url through jWebbrowser.setURL(url); it is working fine. url like http://www.abc.com

But i am getting one problem . when i am sending url with( cookie ) jsessionid then i am not getting response from server. i am getting only session time out.

i am appending cookie as like String url = "http://www.abc.com;JSESSIONID=123456789"

 can you please give me  suggestion  for solving my  problem.

Thanks & Regards

Ramesh K 

 

 

ramesh kancherla replied on Wed, 2008/07/02 - 12:00pm in response to: Wong Qil

Hi Chrriis,

           This is rameshkancherla. I am using DJ Native Swing Project. when i am sending url through jWebbrowser.setURL(url); it is working fine. url like http://www.abc.com

But i am getting one problem . when i am sending url with( cookie ) jsessionid then i am not getting response from server. i am getting only session time out.

i am appending cookie as like String url = "http://www.abc.com;JSESSIONID=123456789"

 can you please give me  suggestion  for solving my  problem.

Thanks & Regards

Ramesh K

ramesh kancherla replied on Wed, 2008/07/02 - 12:06pm

Hi Chrriis,

           This is rameshkancherla. I am using DJ Native Swing Project. when i am sending url through jWebbrowser.setURL(url); it is working fine. url like http://www.abc.com

But i am getting one problem . when i am sending url with( cookie ) jsessionid then i am not getting response from server. i am getting only session time out.

i am appending cookie as like String url = "http://www.abc.com;JSESSIONID=123456789"

 can you please give me  suggestion  for solving my  problem.

Thanks & Regards

Ramesh K

ramesh kancherla replied on Wed, 2008/07/02 - 12:07pm

Hi Chrriis,

           This is rameshkancherla. I am using DJ Native Swing Project. when i am sending url through jWebbrowser.setURL(url); it is working fine. url like http://www.abc.com

But i am getting one problem . when i am sending url with( cookie ) jsessionid then i am not getting response from server. i am getting only session time out.

i am appending cookie as like String url = "http://www.abc.com;JSESSIONID=123456789"

 can you please give me  suggestion  for solving my  problem.

Thanks & Regards

Ramesh K

Christopher Deckers replied on Thu, 2008/07/03 - 12:31am in response to: ramesh kancherla

Hi Ramesh,

DJ NativeSwing uses the SWT browser under the hood, and it does not allow setting cookies...

On the other hand, passing query string parameters is allowed:

http://www.abc.com?JSESSIONID=123456789

but this assumes the server understands that particular parameter. If you control the server, then it might be a solution.

 -Christopher

suresh kumar replied on Thu, 2008/07/17 - 5:39am

Hi Christopher,

   I am new in JAVA Appliction.I used JFlashPlayer,Its working fine.Is it possible to add Keylistner?.I want to exit the JFlashPlayr,if i pressed the ESC Key.

Thanks & Regds,

Suresh

Christopher Deckers replied on Thu, 2008/07/17 - 6:41am in response to: suresh kumar

Hi Suresh,

You could get the underlying component and attach a key listener, but I don't know if they are received so you have to try:

flashPlayer.getWebBrowser().getNativeComponent().addKeyListener(xxx);

A better approach would be to have the Flash application to listen to the key events and send a message to the Java application when it wants to close. Sending a message from a Flash application is shown in the demo. This of course means you have to have control over the Flash application code.

-Christopher

suresh kumar replied on Thu, 2008/07/17 - 7:59am in response to: Christopher Deckers

Thanks.It worked like a charm.

 Suresh

ramesh kancherla replied on Fri, 2008/07/25 - 10:38am in response to: Christopher Deckers

Hi Christopher,

This is Ramesh Kancherla, I am using DJ Native Swing web browser. it is working well when i attempt to use it as single browser. But my requirement is ,i need to show more than one browser screen at a time. if we do this i.e. calling DJ Browser which calls the method runeventpump to open a browser also been used more than once

Then i am getting the *************** Exception. Cant we use the DJ Browser for calling more than once.to show 2 different urls in two screens in my application?

can you please give me suggestion. 

Thanks & Regards

Ramesh K

Christopher Deckers replied on Fri, 2008/07/25 - 12:04pm in response to: ramesh kancherla

Hi Ramesh,

It is hard to tell what the problem is but it should work: I open multiple web browser in different tabs, or on a desktop pane.

The best way for me to help you would be that you send me a simple example with sources by e-mail so that I can test and debug.

Cheers,

-Christopher

ramesh kancherla replied on Sun, 2008/07/27 - 11:54am in response to: Christopher Deckers

Hi Christopher

               I am sending sample code.this code is for one screen. if i am trying to open two screens browsers i am getting error at runeventpump(). can you please give me suggestion.

 

 package browser;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Toolkit;

import javax.swing.SwingUtilities;
import javax.swing.JFrame;

import chrriis.dj.nativeswing.ui.JWebBrowser;
import chrriis.dj.nativeswing.NativeInterfaceHandler;
import chrriis.dj.nativeswing.ui.event.WebBrowserAdapter;
import chrriis.dj.nativeswing.ui.event.WebBrowserEvent;
import chrriis.dj.nativeswing.ui.event.WebBrowserNavigationEvent;
import com.instacoll.livedocuments.oo.configuration.InstaConfig;
import com.instacoll.livedocuments.oo.exception.StringUtils;
import com.instacoll.livedocuments.oo.instasecuremanager.InstaSecureManager;
import com.instacoll.livedocuments.oo.miscellaneous.UserStateManager;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import javax.swing.ImageIcon;

public class AddDocumentProperties extends JFrame {

    private static Runnable xxx;
    final JFrame con = this;
    public static AddDocumentProperties AddDocProp = null;
    private static boolean bThreadStatus = false;
    private static String documentId;
        private String currenturl = "";
    private String prevurl = "";
    JWebBrowser webBrowser;

    public static AddDocumentProperties getInstance() {
        if (AddDocProp == null) {
            AddDocProp = new AddDocumentProperties(documentId);
        }
        return AddDocProp;
    }

    public AddDocumentProperties(String documentID) {
        super("Add Document Properties");
        Class<AddDocumentProperties> clazz = AddDocumentProperties.class;

        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationByPlatform(true);
        String img = InstaConfig.TRAY_ICON_IMAGE;
        img = img.substring(0, img.lastIndexOf("/"));
        setIconImage(new ImageIcon(img + "liveimg.JPG").getImage());

        Container contentPaneF = getContentPane();
        this.setSize(900, 500);

        int x = (Toolkit.getDefaultToolkit().getScreenSize().width - this.getSize().width) / 2;
        int y = (Toolkit.getDefaultToolkit().getScreenSize().height - this.getSize().height) / 2;
        this.setBounds(x, y, this.getSize().width, this.getSize().height);

        webBrowser = new JWebBrowser() {        };
        webBrowser.setMenuBarVisible(false);
        webBrowser.setButtonBarVisible(false);
        webBrowser.setAddressBarVisible(false);
        webBrowser.setStatusBarVisible(false);
//      /instasecure/displayDocumentDetailsPage.do?docId=1230941
//    webBrowser.setURL("http://www.yahoo.com");
//        /instasecure/taskAssignPage.do?docId=1233332
//        GET /instasecure/signAssignPage.do?docId=1233342
        showPage(InstaConfig.APPLICATIONURL + "displayDocumentDetailsPage.do?docId=" + documentID);
//        webBrowser.setURL(InstaConfig.APPLICATIONURL + "displayDocumentDetailsPage.do?docId=" + documentID);
        contentPaneF.add(webBrowser, BorderLayout.CENTER);
        webBrowser.addWebBrowserListener(new WebBrowserAdapter() {

            @Override
            public void commandReceived(WebBrowserEvent e, String command) {
                JWebBrowser web = (JWebBrowser) e.getSource();
                web.getURL();
            }

            @Override
            public void urlChanged(WebBrowserNavigationEvent arg0) {
                String url = arg0.getNewURL();
                if (url.equalsIgnoreCase("about:blank")) {
                } else if (url.contains("http")) {
                    showPage(url);
                } else {
                    if (url.contains("about:blank")) {
                        url = url.substring(11);
                    } else if (url.contains("blank")) {
                        url = url.substring(5);
                    }


                    if (!url.equals("")) {
                        //url = InstaConfig.APPLICATIONURL + url;    
                        url = "http://live.instacoll.com/instasecure/" + url;
                        showPage(url);
                    }

                }
            }
        });
    }

    public AddDocumentProperties() {

    }

    private void showPage(String pageUrl) {

        String inputLine;
        try {
            String cookie = UserStateManager.getInstance().getAuthKey().trim();
            System.out.println(pageUrl);
            prevurl = currenturl;
            currenturl = pageUrl;
            URL url = new URL(pageUrl);
            URLConnection conn = url.openConnection();
            conn = url.openConnection();
            conn.setRequestProperty("Cookie", cookie);
            conn.setRequestProperty("Content-type", "text/html");

            StringBuffer answer1 = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                answer1.append(line);
            }
            reader.close();

//             System.out.print(answer1.toString());
            webBrowser.setText(answer1.toString());
            webBrowser.setVisible(true);

        } catch (Exception ex) {
            InstaSecureManager.logger.log(Level.SEVERE, StringUtils.getStackTrace(ex));
        }
    }
    public void showAddDocProperties(final String docID) {
        documentId = docID;

        if (AddDocProp == null) {
            if (bThreadStatus == false) {
                bThreadStatus = true;
                AddDocProp = new AddDocumentProperties(documentId);
            }
//login.setVisible(true);
            initialise(true);
        } else {
            reinit();
        }
    }

    private static void initialise(boolean bVisible) {
        final boolean bShow = bVisible;
        NativeInterfaceHandler.init();
        Toolkit.getDefaultToolkit().setDynamicLayout(true);
        xxx = new Runnable() {

            public void run() {
                try {
                    javax.swing.UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel");
                    com.birosoft.liquid.LiquidLookAndFeel.setLiquidDecorations(true);
                } catch (Exception e) {

                }
                AddDocProp.setVisible(bShow);
            //login.setAlwaysOnTop(true);
            }
        };

        SwingUtilities.invokeLater(xxx);
            NativeInterfaceHandler.runEventPump();

    }

    private static void reinit() {
        NativeInterfaceHandler.init();
        Toolkit.getDefaultToolkit().setDynamicLayout(true);

        xxx = new Runnable() {

            public void run() {
                try {
                    javax.swing.UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel");
                    com.birosoft.liquid.LiquidLookAndFeel.setLiquidDecorations(true);
                } catch (Exception e) {

                }

                if (bThreadStatus == false) {
                    bThreadStatus = true;
                    AddDocProp = new AddDocumentProperties(documentId);
                }

                AddDocProp.setVisible(true);


            }
        };
        SwingUtilities.invokeLater(xxx);

    }

    public static void main(String[] args) {
        AddDocumentProperties docProp = new AddDocumentProperties();
        docProp.showAddDocProperties("11221");
    }
}

 

 Thanks & Regads

Ramesh K 

ramesh kancherla replied on Tue, 2008/07/29 - 12:11pm

Hi Christopher,

                    This is Ramesh Kancherla. I am using DJ Native Swing web browser. It is working well.

But I  am getting one problem. if I tried to open javascript calendarpopup then browser is displaying empty.

I am not getting calander popup. after i refreshed the browser. my JVM is crashing.

can you please give me sugestion how to solve my problem 

 

Thanks & Regards

Ramesh K 

 

Christopher Deckers replied on Tue, 2008/07/29 - 1:02pm in response to: ramesh kancherla

Hi Ramesh,

Without a proper test case, it is hard for me to help you.

I would recommend you send me an e-mail ( chrriis (at) nextencia (dot) net ) when you face some issues along with a test case when it is possible. E-mails are a better way for me to keep track of this and have a focused discution.

Cheers,
-Christopher

 

Christopher Deckers replied on Tue, 2008/07/29 - 1:08pm in response to: ramesh kancherla

Hi Ramesh,

It seems you are not using the latest version of DJ NativeSwing. Several bugs are fixed and the API is greatly improved, so I suggest you upgrade. Be careful, the API is a bit different: package names have changed, and a few methods have a different name, like NativeInterface.open().

Cheers,
-Christopher

 

puneet dixit replied on Fri, 2008/08/22 - 8:14am

hi

    i  m using linux mandriva 2008.1 and i using dj native jflash player but it shows message that flash plugin is not installed .

    but i have install flash plugin .it still showing same message...

                                  plz help........

  thank you

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.