Changing SplashScreen Image with SplashScreen.setImageURL(link); - java

I've found an example in Oracle docs about SplashScreen. the problem is in this example the link of the image used here is passed as argument in the command line.
I'm trying to change the code so the link is written inside and I don't need to use the command line.
methode setImageURL(URL imageURL) should be able to do the work for me, but it's not accepting my argument (parameter).
I read about URL class, seems like it needs protocol! protocol like http and ftp ? if that's the case, how should my url be for files in my computer ? when I try to put a link from my computer (ex: "C:\plash.gif") it says illege excape character
I even tried to use http link for an image but it give me this error within the URL line:
non-static method setImageURL(URL) cannot be referenced from a static context
here's the code:
package misc;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
public class SplashDemo extends Frame implements ActionListener {
static void renderSplashFrame(Graphics2D g, int frame) {
final String[] comps = {"foo", "bar", "baz"};
g.setComposite(AlphaComposite.Clear);
g.fillRect(120,140,200,40);
g.setPaintMode();
g.setColor(Color.BLACK);
g.drawString("Loading "+comps[(frame/5)%3]+"...", 120, 150);
}
public SplashDemo() {
super("SplashScreen demo");
setSize(300, 200);
setLayout(new BorderLayout());
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("Exit");
m1.add(mi1);
mi1.addActionListener(this);
this.addWindowListener(closeWindow);
MenuBar mb = new MenuBar();
setMenuBar(mb);
mb.add(m1);
URL link= new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif");
SplashScreen.setImageURL(link);
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
Graphics2D g = splash.createGraphics();
if (g == null) {
System.out.println("g is null");
return;
}
for(int i=0; i<100; i++) {
renderSplashFrame(g, i);
splash.update();
try {
Thread.sleep(90);
}
catch(InterruptedException e) {
}
}
splash.close();
setVisible(true);
toFront();
}
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
private static WindowListener closeWindow = new WindowAdapter(){
public void windowClosing(WindowEvent e){
e.getWindow().dispose();
}
};
public static void main (String args[]) {
SplashDemo test = new SplashDemo();
}
}
this is the output:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - unreported exception java.net.MalformedURLException; must be caught or declared to be thrown
at misc.SplashDemo.main(SplashDemo.java:103)
Java Result: 1
BUILD SUCCESSFUL (total time: 4 seconds)
and nothing happens.
P.S: I'm a very beginner with Java, I'm using NetBeans IDE 7.2.1

The splash screen can be displayed at application startup, before the Java Virtual Machine (JVM) starts.
The splash screen window is closed automatically as soon as the first window is displayed by Swing/AWT (may be also closed manually using the Java API, see below).
If your application is packaged in a jar file, you can use the
SplashScreen-Image option in a manifest file to show a splash screen.
Place the image in the jar archive and specify the path in the option.
The path should not have a leading slash.
For example, in the manifest.mf file:
Manifest-Version: 1.0
Main-Class: Test
SplashScreen-Image: filename.gif
The SplashScreen class provides the API for controlling the splash screen.
This class may be used to
close the splash screen
change the splash screen image
get the splash screen native window position/size
paint in the splash screen.
It cannot be used to create the splash screen.
This class cannot be instantiated.
Only a single instance of this class can exist, and it may be obtained by using the getSplashScreen() static method.
In case the splash screen has not been created at application startup via the command line or manifest file option,
the getSplashScreen method returns null.
so what is wrong with your code?
NOT
SplashScreen.setImageURL(link);
OK
splash.setImageURL(link);
wrong sequence : Setting ImageUrl before you have a splash Object
URL link= new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif");
SplashScreen.setImageURL(link);
final SplashScreen splash = SplashScreen.getSplashScreen();
correct : Get splash and then set ImageUrl
short
final SplashScreen splash = SplashScreen.getSplashScreen();
splash.setImageURL(link);
long with catch MalformedURLException to get rid of the error
MalformedURLException : must be caught
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
URL link;
try {
link = new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif");
} catch (MalformedURLException ex) {
System.out.println("MalformedURLException link:77");
return;
}
try {
splash.setImageURL(link);
} catch (NullPointerException | IOException | IllegalStateException ex) {
System.out.println("NullPointer or IO or IllegalState setImageUrl:85");
return;
}
To recognize the difference between the local image file and the image file on the internet . I have made a local blue splash.gif file.
The proceeding is as follows.
Local image is loaded. (SplashScreen-Image option in the manifest file)
Internet image is loaded. (//docs.oracle.com...images/splash.gif)
Application appears.
To get it to work in Netbeans
and not always get the error SplashScreen.getSplashScreen() returned null
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
you must do the following.
in properties point to your local .gif file : -splash:src/misc/images/splash.gif

Related

How to detect which display I clicked on an app on Windows task bar?

I'm developing a Java app which will take a screen shot, I have 3 monitors in my office, so I want my app to be able to take a screen shot of the display I'm interested in. What it can do now is to take a screen shot of each screen and save the 3 files. But I don't want to get 3 file each time I run my Java app. Therefore I want to know if there is a way to detect from which screen my Java app is run, and only take the screen shot of that screen, but my question got no answer : How to determine in which monitor my Java app is running?
I thought about creating a shortcut of my Java app's jar file on desktop, then set it's property's target to : "C:\Program Files\AdoptOpenJDK\jdk-8.0.222.10-hotspot\bin\javaw.exe" -jar C:\Dir_Screen_Shoter\dist\Screen_Shoter.jar
Then I pinned the shortcut to Windows task bar, looking like this :
But the problem is : no matter from which display [ it shows up on every display ] I clicked it, my app always runs [ opens ] on the center [main ] display, so my question is : is there a way I can run this app on the display I clicked it, and that it can detect which monitor it is running from ?
I thought about something like : shift-click, alt-click or hold down ctrl then click on the app on tack bar, but it won't detect all those, so what is a good solution so when I run the app, it will know which display to take a screen shot, it's easy if my app opens a window and let user choose which monitor to act on, but I do not want that, I just want it to take a screen shot without opening an application window.
I've found some related questions, but none of them answers my question :
Show JFrame in a specific screen in dual monitor configuration
How to detect the current display with Java?
[ I tried this one, but it always show device Id == 1 ]
My app looks like this so far :
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Screen_Shoter extends JPanel
{
static Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
static JFrame frame=new JFrame("Screen_Shoter");
static int W=screenSize.width,H=screenSize.height;
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String Result="Screen_Size : "+W+" x "+H+"\n",Dir_Screenshots="C:/Dir_Screenshots/",Screen_Shot_File_Name=Dir_Screenshots+format.format(new Date()).replace("-","_").replace(" ","_").replace(":","_")+"_.png";
JLabel infoLabel=new JLabel();
public Screen_Shoter() // Get ScreenShots From Multiple Monitors
{
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gDevs=ge.getScreenDevices();
if (!new File(Dir_Screenshots).exists()) new File(Dir_Screenshots).mkdirs();
int defaultScreenIndex=getScreenIndex();
Out("defaultScreenIndex = "+defaultScreenIndex+"\n");
for (GraphicsDevice gDev : gDevs)
{
DisplayMode mode=gDev.getDisplayMode();
Rectangle bounds=gDev.getDefaultConfiguration().getBounds();
Out("[ "+gDev.getIDstring()+" ] Min : ( "+bounds.getMinX()+" , "+bounds.getMinY()+" ) ; Max : ( "+bounds.getMaxX()+" , "+bounds.getMaxY()+" ) W = "+mode.getWidth()+" , H = "+mode.getHeight());
try
{
Robot robot=new Robot();
BufferedImage image=robot.createScreenCapture(new Rectangle((int)bounds.getMinX(),(int)bounds.getMinY(),(int)bounds.getWidth(),(int)bounds.getHeight()));
ImageIO.write(image,"png",new File(Screen_Shot_File_Name.replace(".png",gDev.getIDstring().replace("\\","")+".png")));
}
catch (AWTException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
}
infoLabel.setFont(new Font("Times New Roman",0,15));
infoLabel.setForeground(new Color(0,0,218));
infoLabel.setText("<html>"+Result.replace("\n","<P>")+"</html>");
add(infoLabel);
}
int getScreenIndex()
{
int myScreenIndex=-1;
GraphicsConfiguration config=frame.getGraphicsConfiguration();
GraphicsDevice myScreen=config.getDevice();
GraphicsEnvironment env=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] allScreens=env.getScreenDevices();
for (int i=0;i<allScreens.length;i++)
{
if (allScreens[i].equals(myScreen))
{
myScreenIndex=i;
break;
}
}
Out("frame : "+frame.getBounds());
return myScreenIndex;
}
private static void showOnScreen(int screen,Window frame)
{
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd=ge.getScreenDevices();
GraphicsDevice graphicsDevice;
if (screen>-1 && screen<gd.length) graphicsDevice=gd[screen];
else if (gd.length>0) graphicsDevice=gd[0];
else throw new RuntimeException("No Screens Found");
Rectangle bounds=graphicsDevice.getDefaultConfiguration().getBounds();
int screenWidth=graphicsDevice.getDisplayMode().getWidth();
int screenHeight=graphicsDevice.getDisplayMode().getHeight();
frame.setLocation(bounds.x+(screenWidth-frame.getPreferredSize().width)/2,bounds.y+(screenHeight-frame.getPreferredSize().height)/2);
// frame.setLocation(bounds.x,bounds.y);
frame.setVisible(true);
}
private void out(String message)
{
System.out.print(message);
Result+=message;
}
private void Out(String message)
{
System.out.println(message);
Result+=message+"\n";
}
// Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
static void createAndShowGUI()
{
final Screen_Shoter demo=new Screen_Shoter();
frame.add(demo);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setBounds(0,0,600,178);
frame.setLocationRelativeTo(null);
frame.setVisible(true); // For test only
// showOnScreen(0,frame);
}
public static void main(String[] args)
{
// Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } });
}
}
Try having your program look for the mouse pointers location and if on that screen take picture when app is clicked

Java Swing error Exception in thread “AWT-EventQueue-0” java.lang.IllegalArgumentException: input == null [duplicate]

I am having a error for my GUI. Trying to set title bar icon then be included in a Runnable JAR.
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
}
catch (IOException e) {
e.printStackTrace();
}
frame.setIconImage(image);
Here is the error I am getting:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GUI.<init>(GUI.java:39)
at GUI.main(GUI.java:351)
The image is in the correct directory which "resources" folder is the root of the
project file
First of all, change this line :
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
to this :
image = ImageIO.read(getClass().getResource("/resources/icon.gif"));
More info, on as to where lies the difference between the two approaches, can be found on this thread - Different ways of loading a Resource
For Eclipse:
How to add Images to your Resource Folder in the Project
For NetBeans:
Handling Images in a Java GUI Application
How to add Images to the Project
For IntelliJ IDEA:
Right-Click the src Folder of the Project. Select New -> Package
Under New Package Dialog, type name of the package, say resources. Click OK
Right Click resources package. Select New -> Package
Under New Package Dialog, type name of the package, say images. Click OK
Now select the image that you want to add to the project, copy it. Right click resources.images package, inside the IDE, and select Paste
Use the last link to check how to access this file now in Java code. Though for this example, one would be using
getClass().getResource("/resources/images/myImage.imageExtension");
Press Shift + F10, to make and run the project. The resources and images folders, will be created automatically inside the out folder.
If you are doing it manually :
How to add Images to your Project
How to Use Icons
A Little extra clarification, as given in this answer's first
code example.
QUICK REFERENCE CODE EXAMPLE(though for more detail consider, A little extra clarification link):
package swingtest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 7/1/14
* Time: 9:44 AM
* To change this template use File | Settings | File Templates.
*/
public class ImageExample {
private MyPanel contentPane;
private void displayGUI() {
JFrame frame = new JFrame("Image Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new MyPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class MyPanel extends JPanel {
private BufferedImage image;
public MyPanel() {
try {
image = ImageIO.read(MyPanel.class.getResource("/resources/images/planetbackground.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new ImageExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
There's a much easier way to load and set an image as a frame icon:
frame.setIconImage(
new ImageIcon(getClass().getResource("/resources/icon.gif")).getImage());
And thats all :)! You don't even have to use a try-catch block because ImageIcon does not throw any declared exceptions. And due to getClass().getResource(), it works both from file system and from a jar depending how you run your application.
If you need to check whether the image is available, you can check if the URL returned by getResource() is null:
URL url = getClass().getResource("/resources/icon.gif");
if (url == null)
System.out.println( "Could not find image!" );
else
frame.setIconImage(new ImageIcon(url).getImage());
The image files must be in the directory resources/ in your JAR, as shown in How to Use Icons and this example for the directory named images/.

How to embed the broadcast from the camera in the container in Codename1?

In my application there is a video button. Here's the code.
#Override
protected void onGUI1_Button1Action (Component c, ActionEvent event){
try {
String value = Capture.captureVideo();
if (value != null) {
final Form previous = Display.getInstance().getCurrent();
Form preview = new Form("Preview");
preview.setLayout(new BorderLayout());
MediaPlayer pl = new MediaPlayer();
if (!value.startsWith("file:/")) {
value = "file:/" + value;
}
pl.setDataSource(value);
preview.addComponent(BorderLayout.CENTER, pl);
preview.setBackCommand(new Command("Back") {
public void actionPerformed(ActionEvent evt) {
previous.showBack();
}
});
preview.show();
}
} catch (Exception ex) {
Log.e(ex);
Dialog.show("Error", "" + ex, "OK", null);
}
}
I picked up this code from github. I don't want to broadcast the video on full screen. I need a video from camera was built into some container. That container must cover only part of the screen. I have built a GUI and put a container(Media Player) into some part of screen.
How to change the code for this purpose?
You can place a camera view finder right into your app with a new cn1lib: https://github.com/codenameone/CameraKitCodenameOne
Overlaying native widgets has been possible for a year or so by now.
Original answer which was correct when it was written is below:
Embedding camera or overlaying component on the preview screen is not yet available in codename one.
This could be done using native interface with peer component. Have a look at how Native map was implemented here

How to write a splash screen?

I'm making a game using Java.
At the moment, I have several classes. The important ones are:
the LevelBuilder class which, upon it's default constructor being called will create a jframe with the required components and then run a gameloop thread which will update even 1/20th of a second using a backbuffer.
The other class is the MainMenu class which i want to have the main method in and to display my logo in a JFrame.
In the end I want to have the MainMenu draw a splash screen to the JFrame, and then after 5 seconds the LevelBuilder to draw inside the original JFrame, without creating a new one.
Sorry if it's a basic question, I just started learning Java.
Well a splash-screen can simply be added to your jar via the manifest.
The problem is by default it will only show for as long as it takes Swing app to load. Thus the 2nd (3rd 4th etc) execution(s) shows the splash-screen fast as JVM and classes etc used by GUI have already been loaded.
In my game to create a splash that stays for longer I had these 2 methods:
/**
* This will render the splash for longer than just loading components
*
* #return true if there is a splash screen file supplied (set via java or
* manifest) or false if not
* #throws IllegalStateException
*/
private boolean showSplash() throws IllegalStateException {
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
return false;
}
Graphics2D g = splash.createGraphics();
if (g == null) {
return false;
}
for (int i = 0; i < 100; i++) {//loop 100 times and sleep 50 thus 100x50=5000milis=5seconds
renderSplashFrame(g);
splash.update();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
splash.close();
return true;
}
private void renderSplashFrame(Graphics2D g2d) {
//draw anyhting else here
}
which will be called something like:
JFrame frame=...;
...
//show splash
if (!showSplash()) {
JOptionPane.showMessageDialog(null, "SplashScreen could not be shown!", "Splash Error: 0x003", JOptionPane.ERROR_MESSAGE);
}
// set JFrame visible
frame.setVisible(true);
frame.toFront();
Please note as showSplash() says it will return false if there is no splash-screen supplied i.e you have not added one to the manifest.
I also would recommend a read on How to Create a Splash Screen if you already haven't.
Also see this other similar answer/question: Make splash screen with progress bar like Eclipse

Cancel a Java Webstart custom download

when you download a resource in a Java Webstart application there's usually a download progress window displayed which shows the progress of the download. If this window is the default progress window, it has a cancel button. I'm basically trying to implement this cancel button in a custom download progress window.
As there is no method which you could call to cancel the download, I tried to find out how this was done in the default progress window. Because of the implementation with a ServiceManager it's a bit tricky to find the actual implementation. But I finally found this: [jdk-source on googlecode (DownloadServiceImpl)].
When you search for "cancel" or just scroll down to the progress method you will see that it should be as easy as throwing a RuntimeException. Sadly this doesn't really work. It just stops the progress method from being called. The resource is still downloaded in the background and the loadPart method never returns.
If you want to try this for yourself, I've prepared a small example. You will need some sort of webserver though (a local webserver is sufficient of course). I have tried this on a Windows XP (32 bit) with Java 1.6.0_21 (and apache tomcat 6).
A simple jnlp file would look like this (you probably want to change the port):
<?xml version="1.0" encoding="utf-8"?>
<jnlp
spec="1.0+"
codebase="http://127.0.0.1:8080/DownloadTest"
href="DownloadTest.jnlp"
version="1.0">
<information>
<title>DownloadTest</title>
<vendor>Download Tester</vendor>
</information>
<resources os="Windows">
<java version="1.6.0_18+" href="http://java.sun.com/products/autodl/j2se" />
<jar href="DownloadTest.jar" main="true"/>
<jar href="largeResource.jar" download="lazy" part="One"/>
</resources>
<application-desc main-class="downloadtest.Main">
</application-desc>
</jnlp>
Next you will need a large file as resource (the content doesn't matter at all). For example on many windows machines you you will find "driver.cab" under "Windows\Driver Cache\i386". The file must be added to a jar archive (jar -cf largeResource.jar <input file>).
The main program looks like this (you will need to include jnlp.jar as lib, which you can find at <jdk_home>\sample\jnlp\servlet):
package downloadtest;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.jnlp.DownloadService;
import javax.jnlp.DownloadServiceListener;
import javax.jnlp.ServiceManager;
import javax.jnlp.UnavailableServiceException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class Main {
private static DownloadService downloadService;
private static DownloadServiceListener customDownloadWindow;
static {
try {
downloadService = (DownloadService) ServiceManager.lookup("javax.jnlp.DownloadService");
} catch (UnavailableServiceException ex) {
System.err.println("DownloadService not available.");
}
customDownloadWindow = new CustomProgress();
}
public static void main(String[] args) {
JFrame frame = new JFrame("DownloadTest");
frame.setBounds(0, 0, 200, 100);
frame.setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
frame.setLayout(null);
JButton startDownload = new JButton("download");
startDownload.setBounds(20, 20, 150, 40);
startDownload.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() {
try {
downloadService.loadPart("One", customDownloadWindow);
//downloadService.loadPart("One", downloadService.getDefaultProgressWindow());
} catch (IOException ex) {
ex.printStackTrace();
System.err.println("IOException loadPart.");
}
return null;
}
}.execute();
}
});
frame.add(startDownload);
frame.setVisible(true);
}
}
You can try each download progress window by uncommenting one "downloadService.loadPart..." line and commenting out the other one.
And finally the custom progress window itself:
package downloadtest;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.jnlp.DownloadServiceListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
public class CustomProgress implements DownloadServiceListener {
JFrame frame = null;
JProgressBar progressBar = null;
boolean uiCreated = false;
boolean canceled = false;
public CustomProgress() {
}
private void create() {
JPanel top = createComponents();
frame = new JFrame(); // top level custom progress indicator UI
frame.getContentPane().add(top, BorderLayout.CENTER);
frame.setBounds(300,300,400,300);
frame.pack();
updateProgressUI(0);
}
private JPanel createComponents() {
JPanel top = new JPanel();
top.setBackground(Color.WHITE);
top.setLayout(new BorderLayout(20, 20));
String lblText = "<html><font color=green size=+2>JDK Documentation</font>" +
"<br/> The one-stop shop for Java enlightenment! <br/></html>";
JLabel lbl = new JLabel(lblText);
top.add(lbl, BorderLayout.NORTH);
progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
top.add(progressBar, BorderLayout.CENTER);
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CustomProgress.this.canceled = true;
}
});
top.add(cancelButton, BorderLayout.SOUTH);
return top;
}
public void progress(URL url, String version, long readSoFar,
long total, int overallPercent) {
updateProgressUI(overallPercent);
}
public void upgradingArchive(java.net.URL url,
java.lang.String version,
int patchPercent,
int overallPercent) {
updateProgressUI(overallPercent);
}
public void validating(java.net.URL url,
java.lang.String version,
long entry,
long total,
int overallPercent) {
updateProgressUI(overallPercent);
}
public void downloadFailed(URL url, String string) {
System.err.println("Download failed");
}
private void updateProgressUI(int overallPercent) {
if (overallPercent > 0 && overallPercent < 99) {
if (!uiCreated) {
uiCreated = true;
// create custom progress indicator's UI only if
// there is more work to do, meaning overallPercent > 0 and < 100
// this prevents flashing when RIA is loaded from cache
create();
}
progressBar.setValue(overallPercent);
if (canceled) {
throw new RuntimeException("canceled by user");
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
} else {
// hide frame when overallPercent is above 99
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (frame != null) {
frame.setVisible(false);
frame.dispose();
}
}
});
}
}
}
This is basically taken from an Oracle tutorial (http://download.oracle.com/javase/tutorial/deployment/webstart/customProgressIndicatorForAppln.html). I just added a cancel button.
When you build this as a jar file and put it together with the largeResource.jar and DownloadTest.jnlp in a public folder of your webserver, you should be able to start the application via your web browser. Then click the download button and before it is finished click the cancel button in the download window. After trying the custom progress window you will need to remove the application (or just the resource) from your Java cache (because the resource is downloaded in the background regardless of clicking the cancel button).
So, why is this working with the default progress window but not with the custom progress window? Is there an easy possibility to cancel a download with a custom download window?
Any help or hints appreciated.
Drax
Ok, took a look at the Google sample you showed and found this at the bottom of the class
/*
* Progress Helper class
*
* The DownloadServiceListerner interface defined in the JNLP API is
* a subset of the DownloadProgressWindow interface used by elsewhere.
*
* this class is used to create a Helper object that implements both.
*/
private class ProgressHelper extends CustomProgress {
private DownloadServiceListener _dsp = null;
public ProgressHelper() {
_dsp = null;
}
public ProgressHelper(DownloadServiceListener dsp) {
setAppThreadGroup(Thread.currentThread().getThreadGroup());
setListener(dsp);
_dsp = dsp;
if (_dsp instanceof DefaultProgressHelper) {
((DefaultProgressHelper) _dsp).initialize();
}
// for bug #4432604:
_dsp.progress(null, null, 0, 0, -1);
}
public void done() {
if (_dsp instanceof DefaultProgressHelper) {
((DefaultProgressHelper) _dsp).done();
} else {
// make sure callbacks to DownloadServiceListener have
// been called before returning (for TCK test)
flush();
}
}
}
And what is interesting is that it looks like it sets the current thread's ThreadGroup as the application thread group. So this leads me to believe that by doing this the actual download is kept closer to the application (not sure what the correct terminology would be) such that the RuntimeException throw in the class in the cancel check really does affect it.
Otherwise, my hunch is that in your application the download actually takes place in another thread and is "unaffected" by the Exception thrown by your application, hence, allowing it to complete.

Categories