So I'm using VLCJ and the VLC player for java to play a video when I run my program. Problem is, the video player only closes when the user clicks the "x" button. Is there a way to close it automatically when the video ends?
Thanks!
If it helps, here's my code:
//////Main class:
package switchAndAnim;
import java.io.File;
import javax.swing.JFileChooser;
public class Start {
public static void main(String[] args)
{
//location of vlc files, media file
new MediaPlayer("vlc-2.0.2", "ryankilp2.wmv").run();
}
}
///////MediaPlayer class:
package switchAndAnim;
import javax.swing.JFrame;
import com.sun.jna.NativeLibrary;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
public class MediaPlayer {
private JFrame ourFrame = new JFrame();
private EmbeddedMediaPlayerComponent ourMediaPlayer;
private String mediaPath = "";
MediaPlayer(String vlcPath,String mediaURL)
{
this.mediaPath = mediaURL;
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), vlcPath);
ourMediaPlayer = new EmbeddedMediaPlayerComponent();
ourFrame.setContentPane(ourMediaPlayer);
ourFrame.setSize(640,480);
ourFrame.setVisible(true);
ourFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void run()
{
ourMediaPlayer.getMediaPlayer().playMedia(mediaPath);
}
}
The media player has all sorts of events you can listen for, one of them being the "finished" event that fires when the end of the video is reached.
ourMediaPlayer = new EmbeddedMediaPlayerComponent() {
public void finished(MediaPlayer mediaPlayer) {
ourMediaPlayer.release(); // In practice, this line is optional
System.exit(0);
}
}
I used System.exit() since your question set EXIT_ON_CLOSE, but equally you could hide or dispose the frame instead depending on your use case.
Related
I am building a simple program with one button. I want to play the "zvuk.wav" file after I click on the button. It's not working though and I cant solve why. When I click the button, nothing happens. The zvuk.wav file is in the src file with the classes.
Here is my first class which imports java.applet:
package Music;
import java.net.MalformedURLException;
import java.net.URL;
import java.applet.*;
public class Music {
private URL soubor;
public Music(String cesta){
try {
soubor = new URL("file:"+cesta);
} catch (MalformedURLException vyjimka) {
System.err.println(vyjimka);
}
Applet.newAudioClip(soubor).play();
}
}
MainFram which extends JFrame and has one Button:
package Music;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MainFrame extends JFrame{
public static final int WIDTH = 480;
public static final int HEIGHT = 600;
private String file;
public MainFrame(){
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setTitle("Přehrávač");
setResizable(false);
JPanel jPanel = new JPanel();
JButton bPlay = new JButton("PLAY");
jPanel.setLayout(null);
add(jPanel);
jPanel.add(bPlay);
bPlay.setBounds(200, 250, 100, 50);
bPlay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Music music = new Music("zvuk.wav");
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MainFrame();
}
});
}
}
Please note that Applet.newAudioClip(url).play() does not throw an error if it fails for whatever reason (for example nothing will happen if the project cannot find the wav file).
Try this stand alone test app. Does it work?
import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;
public class MainClass {
public static void main(String[] args) {
try {
URL url = new URL("file:zvuk.wav" );
AudioClip ac = Applet.newAudioClip(url);
ac.play();
System.out.println("Press any key to exit.");
System.in.read();
ac.stop();
} catch (Exception e) {
System.out.println(e);
}
}
}
If this small sample works, then it should be a small matter to modify it for your purposes.
However if it doesn't work then we almost certainly know that you project is unable to find the wav file.
Try add this to the code above:
//existing line
URL url = new URL("file:zvuk.wav" );
//new lines to debug wav file location
File myMusicFile = new File(url.getPath());
if(myMusicFile.exists() && !myMusicFile.isDirectory()) {
System.out.println("File exists and is not a directory");
}
If the file does not exist then that's your problem, and you need to point your URL to the correct location.
However if the file does exist and it still doesn't work then we have another possible issue outside of code.
It is possible that .play() is completing too quickly, see below for an example of how to keep it alive.
It is possible that your wav file is not a type that can be played, or it requires an unsupported codec. This is a far bigger topic and needs a new question, and a little bit of research on your part.
Here is the example to keep it alive from the sample code:
//load and start audio
AudioClip ac = Applet.newAudioClip(url);
ac.play();
System.out.println("Press any key to exit.");
//keep thread alive until a key is pressed
System.in.read();
ac.stop();
Sources:
http://www.java2s.com/Code/JavaAPI/java.applet/AppletnewAudioClipURLaudioFileURL.htm
http://docs.oracle.com/javase/7/docs/api/java/applet/AudioClip.html#play%28%29
I do this using NetBeans. This is the code.
Music.java file
package sound.play;
import java.applet.Applet;
import java.net.MalformedURLException;
import java.net.URL;
public class Music {
private URL soubor;
public Music(String cesta) {
try {
soubor = new URL("file:" + cesta);
} catch (MalformedURLException vyjimka) {
System.err.println(vyjimka);
}
Applet.newAudioClip(soubor).play();
}
}
MainFram which extends JFrame and has one Button
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JPanel;
public class MainFrame extends javax.swing.JFrame {
public static final int WIDTH = 200;
public static final int HEIGHT = 200;
private String file;
public MainFrame() {
initComponents();
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setTitle("Přehrávač");
setResizable(false);
JPanel jPanel = new JPanel();
jPanel.setLayout(null);
add(jPanel);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Music music = new Music("zvuk.wav");
String filename = "zvuk.wav";
URL url = this.getClass().getResource(filename);
File myMusicFile = new File(url.getPath());
AudioClip ac = Applet.newAudioClip(url);
ac.play();
System.out.println("Press any key to exit.");
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainFrame().setVisible(true);
}
});
}
I'm trying to make a function to play an audio when an user clicks a button. The problem is that when I tried to pass in the fileName from the parameter using "fileName.addActionListener", it says that fileName cannot be found even though it's referenced in the parameter. What did I do wrong, and how can I fix this? Thanks.
package sunaudiodemo;
import static java.awt.Color.blue;
import static java.awt.Color.green;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import sun.audio.*; //import the sun.audio package
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class SunAudioDemo {
public static void playAudioOnClick (final String fileName) {
//*******************************************
fileName.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
playAudio(fileName);
} catch (Exception ex) {
Logger.getLogger(SunAudioDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
//*******************************************
}
public static void playAudio (String text) throws Exception {
// identify the sound file as a File class object
File soundFile = new File(text);
// Open an input stream for the File object soundFile
// This allows Java to read the file.
InputStream inFile = new FileInputStream(soundFile);
// Create an AudioStream from the input stream.
// This tells Java to read the incoming data as sound data.
AudioStream audio = new AudioStream(inFile);
// play the sound file using the start method from Audioplayer.player
AudioPlayer.player.start(audio);
}
public static void main(String[] args) throws Exception {
// create a frame to hold our components
JFrame myJFrame = new JFrame();
// create a new a grid layout for the frame - 5 rows x 2 cols, gaps=20
GridLayout myLayout = new GridLayout(5,2);
myLayout.setHgap(20);
myLayout.setVgap(20);
// assign myLayout to be the layout for MyJFrame
myJFrame.setLayout(myLayout);
// Create a button with text OK
JButton wav1 = new JButton("Play Audio 1");
myJFrame.add(wav1); // Add the OK button
playAudioOnClick("wav2.wav");
// set the title, size, location and exit behavior for the JFrame
myJFrame.setTitle("Play Audio");
myJFrame.setSize(360, 480);
myJFrame.setLocation(200, 100);
myJFrame.getContentPane().setBackground( green );
myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// make the frame visible (activate the frame)
myJFrame.setVisible(true);
} // end main()
} // end class SunAudioDemo
In the code above, fileName is defined as a String. Assuming this is java.lang.String, there is no method addActionListener(). You need to pass in a reference to your button so you can add the ActionListener to it.
Can I use a filename to something in java without needing the full path? IE,
cashOutSound = Applet.newAudioClip(new URL("file:C:\\Users\\Wilson\\IdeaProjects\\Millionaire\\src\\sounds\\cashout.wav"));
Becomes problematic as I move my program across computers. Compiling to a jar doesn't seem to help.
Try
URL url = getDocumentBase();
AudioClip audioClip = getAudioClip(url, "music/JButton.wav")
Project sturcture
Sample code:
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class PlaySoundsApplet1 extends Applet implements ActionListener {
private static final long serialVersionUID = 1L;
private Button play, stop;
private AudioClip audioClip;
public void init() {
URL url = getDocumentBase();
audioClip = getAudioClip(url, "music/JButton.wav");
play = new Button("Play");
add(play);
play.addActionListener(this);
stop = new Button("Stop");
add(stop);
stop.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {
Button source = (Button) ae.getSource();
if (source == play) {
audioClip.play();
} else if (source == stop) {
audioClip.stop();
}
}
}
I followed some tutorials about combining JavaFX with Swing (JFrame) to play a video, however all I get is a black screen where the video is supposed to be without any actual content playing, No errors are reported either.
What am I doing wrong here and why wont the video play?
I tried several .flv videos, none of them will start playing (they do play when I open them in my browser)
I'm running jre7 and jdk1.7.0_45 on windows 8.1 N Pro with the K-lite full codec pack installed
EDIT: updated my code after the comment of jewelsea, nothing has changed, the black box still appears without content playing, the console doesn't show any text coming up
package com.example.test;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.media.Media;
import javafx.scene.media.MediaErrorEvent;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.paint.Color;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initAndShowGUI();
}
});
}
private static void initAndShowGUI() {
// This method is invoked on the EDT thread
JFrame frame = new JFrame("Test");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setSize(640, 480);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Platform.runLater(new Runnable() {
#Override
public void run() {
initFX(fxPanel);
}
});
}
private static void initFX(JFXPanel fxPanel) {
// This method is invoked on the JavaFX thread
Scene scene = createScene();
fxPanel.setScene(scene);
}
private static Scene createScene() {
String source;
Media media;
MediaPlayer mediaPlayer;
MediaView mediaView = null;
try {
media = new Media("http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv");
if (media.getError() == null) {
media.setOnError(new Runnable() {
public void run() {
// Handle asynchronous error in Media object.
System.out.println("Handle asynchronous error in Media object");
}
});
try {
mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
if (mediaPlayer.getError() == null) {
mediaPlayer.setOnError(new Runnable() {
public void run() {
// Handle asynchronous error in MediaPlayer object.
System.out.println("Handle asynchronous error in MediaPlayer object");
}
});
mediaView = new MediaView(mediaPlayer);
mediaView.setOnError(new EventHandler() {
public void handle(MediaErrorEvent t) {
// Handle asynchronous error in MediaView.
System.out.println("Handle asynchronous error in MediaView: "+ t.getMediaError());
}
#Override
public void handle(Event arg0) {
// TODO Auto-generated method stub
System.out.println("Handle asynchronous error in MediaView arg0: "+arg0.toString());
}
});
} else {
// Handle synchronous error creating MediaPlayer.
System.out.println("Handle synchronous error creating MediaPlayer");
}
} catch (Exception mediaPlayerException) {
// Handle exception in MediaPlayer constructor.
System.out.println("Handle exception in MediaPlayer constructor: "+ mediaPlayerException.getMessage());
}
} else {
// Handle synchronous error creating Media.
System.out.println("Handle synchronous error creating Media");
}
} catch (Exception mediaException) {
// Handle exception in Media constructor.
System.out.println("Handle exception in Media constructor: "+mediaException.getMessage());
}
Group root = new Group();
Scene scene = SceneBuilder.create().width(640).height(480).root(root).fill(Color.WHITE).build();
if(mediaView != null) {
root.getChildren().add(mediaView);
}
return scene;
}
}
So I installed the windows media feature pack in order to get adobe premiere pro working (because it required a dll file from windows media player (which I didn't had installed because I run an N version of windows) and now the video does play for me.
I can't say with 100% confirmation the cause was not having WMP installed as the media feature pack might as well have installed something else that solved my problem, nonetheless, problem solved :)
I want to thank the other answers for trying, I really appreciate it.
Please do not mind if i am writing this answer. I know this is a very old question but this answer might help others. I am currently developing a JavaFX application which needs to execute a file depending upon its type.
My application played the video for the first time but when i clicked on another mp4 video file it didn't play.
Here is my initial code.
private void playVideo(String fileLocation) {
System.out.println("VideoProcesser Thread = " + Thread.currentThread().getName());
media = new Media(new File(fileLocation).toURI().toString());
mediaPlayer = new MediaPlayer(media);
mediaView = new MediaView(mediaPlayer);
runnable = () -> {
System.out.println("Inside runnable VideoProcesser Thread = " + Thread.currentThread().getName());
mediaPlayer.play();
};
mediaPlayer.setOnReady(runnable);
setVideoMediaStatus(PLAYING);
pane.getChildren().add(mediaView);
}
Then since the video player screen was dark, i thought the problem was with media view, so i added the following two line,
if(mediaView == null) {
mediaView = new MediaView(mediaPlayer);
}
mediaView.setMediaPlayer(mediaPlayer);
Now, when i click on different videos my application just plays fine.
Here is the complete code.
Media media;
MediaPlayer mediaPlayer;
MediaView mediaView;
private void playVideo(String fileLocation) {
System.out.println("VideoProcesser Thread = " + Thread.currentThread().getName());
media = new Media(new File(fileLocation).toURI().toString());
mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
if(mediaView == null) {
mediaView = new MediaView(mediaPlayer);
}
mediaView.setMediaPlayer(mediaPlayer);
mediaPlayer.play();
mediaPlayer.setOnError(() -> System.out.println("Current error: "+mediaPlayer.getError()));
setVideoMediaStatus(PLAYING);
pane.getChildren().add(mediaView);
}
Note that if you are using FXML to instantiate mediaView, then do not instantiate it again. Instantiating it again might make mediaView loose the reference of original node.
Refer to this post and answer by itachi,
javafx mediaview only the audio is playing
try this, it works for me:
package de.professional_webworkx.swing;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javax.swing.JFrame;
public class MyFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Create a new Frame, set title, ...
*/
public MyFrame() {
this.setTitle("Swing and JavaFX");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(1024, 768);
// create a JFXPanel
final JFXPanel jfxPanel = new JFXPanel();
// add the jfxPanel to the contentPane of the JFrame
this.getContentPane().add(jfxPanel);
this.setVisible(true);
Platform.runLater(new Runnable() {
#Override
public void run() {
jfxPanel.setScene(initScene());
}
});
}
public static final void main (String[] args) {
new MyFrame();
}
/**
* init the JFX Scene and
* #return scene
*/
private Scene initScene() {
Group root = new Group();
SceneBuilder<?> sb = SceneBuilder.create().width(640).height(400).root(root);
Media video = new Media("http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv");
MediaPlayer mediaPlayer = new MediaPlayer(video);
mediaPlayer.setAutoPlay(true);
mediaPlayer.play();
MediaView view = new MediaView(mediaPlayer);
root.getChildren().add(view);
Scene scene = sb.build();
return scene;
}
}
Patrick
I took your code and tried running it on my machine (Win7 JDK 1.7.0_25) and got the same results. Black box and no video.
I noticed you aren't setting mediaPlayer.setAutoPlay(true) so I added that call to the createScene() right before mediaPlayer is passed to MediaView. Now the playback seems to work for me.
// ... prior code omitted
// added this to OP's code
mediaPlayer.setAutoPlay(true);
mediaView = new MediaView(mediaPlayer);
mediaView.setOnError(new EventHandler() {
public void handle(MediaErrorEvent t) {
// Handle asynchronous error in MediaView.
System.out.println("Handle asynchronous error in MediaView: "+ t.getMediaError());
}
// ... additional code omitted
Edit: The autoPlay property defaults to false - you can call mediaPlayer.isAutoPlay() to check this. Without either calling mediaPlayer.setAutoPlay(true) or mediaPlayer.play() the video will never start playing.
Edit 2: I just noticed in the comments on another answer that you are having trouble playing the video outside of JavaFX. If you don't already have it installed, try downloading VLC to see if the video can play using that. I believe installing ffdshow tryouts will provide the necessary codecs to play FLV in Windows Media Player. (Although I thought all versions of K-lite codec pack included FLV support)
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.