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();
}
}
}
Related
I recently started to use multithreading in Java and I've run into a problem I assume is due to missing synchronization.
This is a ImageLoader I wrote:
package util;
import javax.swing.ImageIcon;
public class ImageLoader extends Thread {
private String file;
private ImageIcon icon;
public ImageLoader(String file) {
this.file = file;
}
#Override
public void run() {
ImageIcon icon = new ImageIcon(this.file);
this.icon = icon;
super.run();
}
public synchronized ImageIcon returnIcon() {
return this.icon;
}
}
I use this ImageLoader in my GUI-Class:
package gui;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import util.ImageLoader;
public class HauptGui extends JComponent {
public HauptGui() {
initUI();
}
private void initUI() {
int bilderAnzahl = 3;
this.setLayout(new GridLayout(1, 1));
JPanel bilderPanel = new JPanel(new GridLayout(bilderAnzahl, 1));
for (int i = 0; i < bilderAnzahl; i++) {
JLabel jbl = new JLabel();
ImageLoader loader = new ImageLoader("./Picture.jpg");
loader.start();
jbl.setIcon(loader.returnIcon());
jbl.setBorder(BorderFactory.createEtchedBorder());
jbl.setPreferredSize(new Dimension(200, 50));
bilderPanel.add(jbl);
}
JScrollPane scrPn = new JScrollPane(bilderPanel);
this.add(scrPn);
}
}
The Problem is that the returnIcon-Method of the ImageLoader gets called before the Thread calls the run-Method, therefore the ImageIcon is still null.
How do I synchronize this?
No, your problem has nothing to do with synchronization and all to do with simply requesting the image object before it has been created. The solution is to get the image object in a call-back, after it has completed its loading. A SwingWorker would work well in this situation, where you get the image object from the SwingWorker in the worker's done method by calling .get() on it, or you could use a PropertyChangeListener for your callback. See Lesson: Concurrency in Swing for the details on how to use SwingWorkers.
For example (code not tested)
public class ImageLoader2 extends SwingWorker<BufferedImage, Void> {
private String path = ""; /// String to resource path
public BufferedImage doInBackground() throws Exception {
return ImageIO.read(ImageLoader2.class.getResource(path));
}
}
and then run it like:
ImageLoader2 loader = new ImageLoader2();
loader.addPropertyChangeListener(pce -> {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
BufferedImage img = loader.get();
ImageIcon icon = new ImageIcon(img);
// use icon here...
} catch catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
// handle exception here
}
}
});
loader.execute();
Side notes
you should almost never extend Thread.
Don't get the image as a File as you are doing but rather get it as a resource and use ImageIO.read(...) to do this
The resource path is relative to the class-path, not to the user's directory, and so it will likely be different from the path you use to get the image as a file.
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);
}
});
}
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.
I have 3 clasess : Loader, MyDialog and TEST(with main method). (for code see below)
Everything I want to achieve is create simple dialog with JLabel and JProgressBar, which will notify user about how much time remains to show MyDialog. MyDialog is Jdialog with time consuming operation in constructor (loading data from database etc.).
In code below is model situation. When "MyDialog" is created by main (constant BY_USER is false), everything working exactly i want to. But when i make dialog with button , and instance of MyDialog is created after button press (constant BY_USER is true), Loader is blank white form. It looks like is not completed.
Loader is extending Thread, so i suppose that problem will be in threading (event dispatch thread)? I dont know, what is wrong and how fix it. Please help.
Thanks and sorry for my English.
CLASS TEST :
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class TEST {
public static final boolean BY_USER = false;
public static void main(String[] args) {
if (BY_USER) {
JFrame mainDialog = new JFrame("Main");
JButton show = new JButton("Show MyDialog");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MyDialog dialog = new MyDialog();
}
});
mainDialog.add(show);
mainDialog.setLocationRelativeTo(null);
mainDialog.setMinimumSize(new Dimension(160, 80));
mainDialog.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainDialog.setVisible(true);
} else {
MyDialog dialog = new MyDialog();
}
}
}
CLASS MyDialog :
package test;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class MyDialog extends JFrame{
public MyDialog() {
super();
// making loader with title, first message and count of steps of operation
Loader loader = new Loader("Loader", "First showed message", 100);
loader.ShowLoader();
// time-consuming operation (loading data from database etc.).
// for clarity replaced with for statement
int j=0;
for(int i=0; i<Integer.MAX_VALUE; i++)
{
j++;
if(j==Integer.MAX_VALUE/100){
// updating loader message and progress bar value
loader.NewAction(Integer.MAX_VALUE - i+"");
j=0;
}
}
// closing loader
loader.DestroyLoader();
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
CLASS Loader:
package test;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
public class Loader extends Thread{
private JDialog dialog;
private JLabel message = new JLabel("", SwingConstants.CENTER);
private JProgressBar progressBar = new JProgressBar(0, 100);
private String newMessage;
private double percentForStep;
private int remainingSteps;
public Loader(String taskName, String firstMessage, int steps) {
this.remainingSteps = steps-1;
dialog = new JDialog((Dialog) null, taskName);
dialog.setLayout(new BorderLayout(15, 15));
dialog.add(message, BorderLayout.CENTER);
dialog.add(progressBar, BorderLayout.SOUTH);
message.setText(firstMessage);
percentForStep = 100 / steps;
}
public void ShowLoader()
{
dialog.setMinimumSize(new Dimension(400,120));
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
this.start();
}
public void DestroyLoader(){
dialog.dispose();
this.interrupt();
}
public void NewAction(String newMessage){
this.newMessage = newMessage;
this.remainingSteps--;
Lock.changed = true;
}
public int RemainingStepsCount()
{
return remainingSteps;
}
#Override
#SuppressWarnings({"CallToThreadYield", "SleepWhileInLoop"})
public void run() {
do{
synchronized (Lock.class) {
if (Lock.changed) {
Lock.changed = false;
this.message.setText(newMessage);
this.progressBar.setValue((int)(100-(remainingSteps*percentForStep)));
dialog.repaint();
}
dialog.repaint();
}
}while(true);
}
}
class Lock{
static boolean changed = false;
}
Look to SwingWorker and his use; I think it can help you to solve the problem.
I have a Java program which is launched from a browser, running with various java.awt.Button buttons. When clicked, it's fine. But when a key is pressed that corresponds to that button, Windows makes the "Default Beep" sound.
The buttons are created like this:
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.io.*;
import java.awt.Panel;
import java.awt.Button;
import java.awt.Font;
import java.awt.event.*;
import java.lang.Integer;
public class buttonPne extends Panel implements ActionListener, constants {
private pClient parent = null;
private labelPne buttonLabel[] = new labelPne[8];
private Panel buttonPanel[] = new Panel[8];
public Button theButtons[] = new Button[8];
private boolean buttonStatus[] = new boolean[8];
public buttonPne(pClient c) {
parent = c;
this.setLayout(new GridLayout(1, 8, 1, 0));
for (int i = 0; i < 8; i++) {
buttonLabel[i] = new labelPne(parent);
buttonLabel[i].setSize(9, 9);
theButtons[i] = new Button();
theButtons[i].setFont(ButtonFont);
theButtons[i].setActionCommand(Integer.toString(i));
theButtons[i].addActionListener(this);
theButtons[i].addKeyListener(parent);
buttonPanel[i] = new Panel();
buttonPanel[i].setBackground(backgroundColor);
buttonPanel[i].setLayout(new BorderLayout());
buttonPanel[i].add("North", theButtons[i]);
buttonPanel[i].add("South", buttonLabel[i]);
this.add(buttonPanel[i]);
}
Deactivate();
}
The key presses are handled like this:
import java.awt.event.KeyEvent;
...
public class pClient extends Applet implements KeyListener, constants {
...
f.addKeyListener(this);
...
public void keyPressed(KeyEvent evt) {
int theKey;
theKey = evt.getKeyCode();
switch(theKey) {
case KeyEvent.VK_1:
case KeyEvent.VK_F1:
buttons.DoButton(0);
break;
...
public void DoButton(int theNumber) {
if (buttonStatus[theNumber]) {
if (parent.pollSendFlag(BUTTONS)) {
parent.chat.takeFocus();
parent.compass.Deactivate();
Deactivate();
}
}
return;
}
How can I stop the default beep from happening on key presses?
Use Swing components instead of AWT components.