Can anyone tell me why does this timer run only once?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimerTest implements ActionListener{
private Robot r;
private Timer t;
private int i;
public TimerTest(){
i = 0;
try {
r = new Robot();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t = new Timer(1000, this);
t.setRepeats(true);
t.start();
}
public static void main(String [] args){
new TimerTest();
}
#Override
public void actionPerformed(ActionEvent arg0) {
i++;
System.out.println("Action..." + i);
}
The funny thing is that, if I decrease the delay in the Timer to just 100, it works as expected. And what's even funnier is that if I delete the code in which I initialize the Robot, it doesn't work at all, the program terminates as soon as I run it.
I've tried this on Windows 7 and on Ubuntu (although on Ubuntu I couldn't use the Robot at all, since I get an exception. Something related to rights, maybe).
Your main is processed so the program stops. You can test it by using this code, adding it to TimerTest()
JFrame testFrame = new JFrame();
testFrame.setVisible(true);
testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
That JFrame keeps your main not from finshing, when you close the Frame the TimerTest ends. Which concludes your main which causes the main to finsh. Ending the program and stoping your swing timer.
See "main exits before javax.swing.Timer's start() can start" at the bug database.
Evaluation
Described behavior - when application exits before Swing timer is started - is correct. Here is what's going then:
Swing timer is created.
Separate thread for swing timer is started. It will notify attached actionListeners when the timeout is passed by posting an instance of InvocationEvent to EDT.
Main thread exits.
At this moment there is no non-daemon threads running in JVM. Application is terminated.
..the evaluator goes on to add..
..This looks like a RFE rather than a defect.
One surefire way to make it behave is to create a GUI element and display it. Which is why I asked earlier..
..why exactly are you creating the timer without any GUI elements? Is this for repeated screen-shots?
To handle that situation, I would typically create and show a frame to allow the user to configure the rate and area for screenshots, then minimize the frame and begin processing when the user clicks:
Screen Capture!
Related
I have a plugin for an application containing a GUI (Swing) and is started as a thread. The GUI starts a thread that does some processing on a buttonevent, right after disposing itself. While processing, a dialog window functions as a logger. Everything works fine, the GUI and dialog window will close and the threads terminate, when calling window.dispose() after the processing finished.
Threads are started as Threads, not via SwingUtilities (I tried many times, but i just can't get that to work).
Basicly the entry class for the application:
public void calledByApplication(){
RunnableClass.startGui(this);
}
public void doStuff(){ //GUI actually gets created here
gui.setVisible(true);
}
public void calledWhenSaveButtonPressed(){
//Process some stuff
gui.dispose(); //works, thread terminates
}
RunnableClass (implements Runnable):
ApplicationEntryClass aec;
public RunnableClass(ApplicationEntryClass aec){
this.aec = aec;
}
public void run(){
aec.doStuff();
}
public static void startGui(ApplicationEntryClass aec){
Thread guiThread = new Thread(new RunnableClass(aec));
guiThread.start();
}
Gui Class:
public void calledWhenSaveButtonPressed(){
aec.calledWhenSaveButtonPressed();
}
public void calledWhenCancelButtonPressed(){
this.dispose(); //doesn't work
}
My problem:
When trying to dispose the GUI via button event (or the x with JFrame.DISPOSE_ON_CLOSE), it closes, but the thread doesn't terminate. After looking at the stack i noticed, that the EventDispatchThread gets stuck on EventDispatchThread.pumpEventForFilter(...).
I'm well aware, that the issue could be, that the thread doesn't get automatically destroyed. But since i'm new to threading i don't really know where to start troubleshooting. Any suggestions?
Edit: The dialog window is not the problem. Also, i can't use System.exit() or else the application calling the plugin will terminate.
i have problem in java and I do not know him and I resolved.
I created a simple program that inserts into the text JPanel using for and sleep function.
Like this(This is an example):
public class example{
JFrame frame....
..
..
public example(){
//ini frame and label.. then..
String s = "abcqweewqewqewqewqweqwqeweqweqwq";
//DO ANIMATION
try
{
for(int i = 0;i<s.length();i++)
{
JLABEL.append(String.valueOf(s.charAt(i)));
Thread.sleep(10);
}
}catch(Exception ex){}
}
public static void main.......{
new example();
}
}
It works perfectly (writes characters after a certain time interval)
But, if i call this main using other class-So waiting until everything renders and then the window appears (so does not animation).
Where is a problem? I hope, you understand me.
Swing is single threaded, and properly written swing code runs in the event dispatch thread. Your sample breaks the threading rule by creating the GUI outside the EDT, and also runs the loop in the main thread. Normally, when created correctly in the EDT, or as a response to an event from a button click or similar, the loop blocks the event dispatch thread so that no drawing can happen until the loop has completed.
You get that behaviour if you initialize the GUI in the event dispatch thread:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new example()
}
});
}
The proper way, instead of sleeping in the EDT, is using a Swing Timer.
To sum the above: your code appears to work only because it has the bug that it runs some of the UI code outside the event dispatch thread.
Within a Java swing application, the following snippet is supposed to play a siren. It starts OK but stops prematurely, not always at the same time (i.e. sometimes it stops almost immediately and sometimes after a longer delay, but usually it does not finish playing the whole sound file). What could be causing this?
I've done my best to create a minimal example that still has the problem:
package monster;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.io.File;
import javafx.embed.swing.JFXPanel;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example_2 extends JPanel {
protected static final long serialVersionUID = 1L;
public Example_2() {
setPreferredSize(new Dimension(100,100));
setBackground(Color.white);
createPanel();
}
public static void main(String[] args) {
Example_2 e = new Example_2();
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.add(e, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
f.repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
new Thread(
new Runnable() {
public void run() {
try {
File f = new File("sound/siren_short.wav");
String url = "file:///"+f.getAbsolutePath().replaceAll("\\\\","/").replaceAll(" ", "%20");
MediaPlayer mp = new MediaPlayer(new Media(url));
mp.play();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public static JFXPanel createPanel() {
return new JFXPanel();
}
}
In the current example code "Example2" posted, it looks to me like the main() executes and exits. Yes, the call to MediaPlayer launches a background thread, but I'm guessing when the main() ends, this terminates the MediaPlayer thread as well (perhaps because it only has daemon status). I haven't used the MediaPlayer yet, myself, so I don't know if this behavior can result or not.
Here is a simple test for you: add the following line.
Thread.sleep(5000); // pauses 5 seconds
or something similar to the end of the main(), after the repaint() call. The number is milliseconds: use a number that is longer than the length of your sound. Does the sound now play to completion? You'll probably have to put the new line of code in a try...catch block.
Check out the api for Thread() when you get a chance. When you get to the page, I'd recommend doing a search on "daemon". There are methods for testing or setting daemon status, plus a terse explanation of what the status means. There is a chance that if you set your runnable to not be a daemon, the program (as shown) will play once and then hang with no way to terminate it except killing it via Eclipse (if it was run in Eclipse) or via an OS task manager.
I haven't delved much into debugging threads in Eclipse--am afraid I can't offer any suggestions there.
Andrew Thompson made a good suggestion, to make use of Clip. This has the benefit of keeping us in "familiar" territory. I've used Clip frequently, but not JavaFX libraries. If you had used Clip, the line of code I'm suggesting (Thread.sleep) would definitely have been needed to allow the sound to play to completion.
Here is a theory: the code which loads and executes the play() command is non-daemon. However, the background processes which deliver the sound data to the line are daemon. If that were the case, then the behavior I describe (termination after the main thread is done) would be consistent.
I just encountered a problem when trying to add an imprint to a swing application which is shown for five seconds when the application is closed.
I had planned to open a JDialog just containing a simple image when the main frame is closed.
I got a function showing the JDialog (I removed everything which is not necessary).
public static void show() {
JDialog d = new JDialog();
JLabel l = new JLabel(new ImageIcon(MainController.class.getClass().getResource("/path/to/endlogo.png")));
d.add(l);
d.setVisible(true);
}
The function is called by the following snippet (in the window listener of my main window)
#Override
public void windowClosing(WindowEvent e) {
show();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The problem is that the dialog is shown AFTER the five seconds (which is when the windows is already closed and the application exited, I tested it and it showed up perfectly after five seconds when run on application start).
Do you guys know a way to achieve it the other way round?
You're blocking the UI thread. Don't do that, basically... use a swing timer or something similar if you want to do something on the UI thread at a later time.
Golden rules:
Don't do anything time consuming on the UI thread
Only access the UI on the UI thread
I have look all over the web, and found no solution to my problem. For a AP Comp Sci project, I am making a Set of games, that will be run from a JFrame with JButtons. I have the games all ready, along with action listeners, but the games dont launch properly. The JFrame and JButtons are all setup correctly too.
private static class TetListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
GameCenter.quit();
GameCenter.startTetris();
}
}
GameCenter.quit() does nothing but run JFrame.dispose(), and GameCenter.startTetris(); constructs a new Tetris object, then run the play() method to start the game. All of Tetris is coded properly and works correctly when it is run in the main method (outside the actionlistener). But as soon as I put it in the ActionListener, it fails to be constructed properly. I tracked the problem down to:
public BlockDisplay(BoundedGrid<Block> board)
{
this.board = board;
grid = new JPanel[board.getNumRows()][board.getNumCols()];
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() // <<<<<<<<<<------------------- Problem Here
{
public void run()
{
createAndShowGUI(); // <<<<<<<<<<<<-------- Never Run
}
});
//Wait until display has been drawn
try
{
while (frame == null || !frame.isVisible()) // <<<<<<<-------- Never Resolved
{
Thread.sleep(1);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
So the program always hangs. I also made a Pacman game that uses this SwingUtilities.invokeLater, so it doesnt work either. I cant figure out why this is happening or how to fix it.
Any help is appreciated. Let me know if you need any more info.
If the thread that runs SwingUtilities.invokeLater is already the swing event thread and you run in this while loop, yup, your application will hang.
Get rid of the while loop.