Here is my main class
import javax.swing.Timer;
public class Test {
public static int k=9;
public static void main(String[] args) {
Timer t = new Timer(100, new Loop());
t.start();
}
}
And my class Loop which implements ActionListener
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Loop implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(Test.k==9){
System.out.println("Its's Working");
}
}
}
I don't know why? When I've fully what it need but it doesn't print "Its's Working" in the console
And one more question is that "Is this Timer class similar to Thread in java ?"
Thanks for your answer!
Your program exits immediately after stating the timer, giving it no chance to fire.
The AWT Event Dispatch Thread (EDT) will need to have started for some reason in order for the timer to stay alive.
Swing is supposed to be use from this thread. If you do so, it should work.
java.awt.EventQueue.invokeLater(() -> {
Timer t = new Timer(100, new Loop());
t.start();
});
To avoid indenting a lot of code , and to have a short main, I tend to create a method call go and use a method reference.
java.awt.EventQueue.invokeLater(Test::go);
private static void go() {
Related
So i want to print out a word every second for 10 seconds, but nothing is working
Here's my code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Main{
public static void main (String[] args){
class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.println("helo");
}
}
ActionListener dummy = new TimerListener();
Timer power_up_time = new Timer(10000,dummy);
power_up_time.addActionListener(dummy);
power_up_time.start();
}
}
EDIT: so i added the start function and it still doesnt work
I believe that you need to start a Timer in order to make it work.
Something like this:
Timer timer = new Timer(500, new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
timer.start();
In newer versions of Java (from the last ten years or so) I would suggest using a ScehduledExecutorService
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleAtFixedRate(() -> System.out.println("hello"), 0, 1, TimeUnit.SECONDS);
TimeUnit.SECONDS.sleep(10);
ses.shutdown();
If the code you posted is complete you are starting the timer right before the application (i.e. the main thread) terminates. Thus the scheduler won't run long enough to execute the timer.
Try sleeping or running in a loop with some exit condition (that's probably what you'll want to do anyways).
You do not initialize and start the Swing toolkit, hence your application immediately terminates.
If you really want to use the Swing Timer, you need to show at least some window or dialog, so that the Swing event thread is running, e.g. by adding the following to the end of your main() method:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JFrame("Frame title").setVisible(true);
}
});
See the other answers for alternatives outside of Swing.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class TimeController {
public static void main(String arg[]){
TimeController m = new TimeController();
System.out.println("starting");
m.start();
}
Timer timer = new Timer (1000, new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Running");
}
});
public void start(){
timer.start();
}
}
I think there is no fault at all.
The Timer starts its task in the background
Your application terminates before the first execution of the Timers method takes place.
For testing you could add
try {
Thread.sleep(5000);
} catch(Exception e){
// Add exception handling
}
right after `m.start();
For some reason the Timer needs to fire at least once to prevent the program from termination. After it fires once, it does hold the program running, even after the main method terminates.
Probably the bug got unnoticed as this is a rather unusual work flow. Delay the termination of the main thread as proposed by #StefanFreitag.
i know multithreading a bit but not in vast and i think the problem is of multithreading. I am calling a method to set label's text by invoking a new thread and leaving it blank after a specified time. I am getting the desired output every time but not only the place which i am going to show you by my piece of code. I am expecting that message should be set and disappeared after the specified time and the window should be minimized after that time. But what actually happening is when it is going to the other thread main thread execution starts and goes for sleep for 5 sec and the message is not appearing and after 5 sec window is getting minimized without showing the message which i am setting on the label.
(Main thread)
Validation.setMessageOnLabel("Username and password has been copied", jLabel15,1.5F);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
Logger.getLogger(PasswordManager.class.getName()).log(Level.SEVERE, null, ex);
}
setState(ICONIFIED);
validation.java (setMessageOnLabel())
static public void setMessageOnLabel(final String msg, final JLabel label, final float time)
{
new Thread(new Runnable() {
#Override
public void run() {
label.setText(msg);
try {
Thread.sleep((long) (time*1000));
} catch (InterruptedException ex) {
Logger.getLogger(PasswordManager.class.getName()).log(Level.SEVERE, null, ex);
}
label.setText("");
}
}).start();
}
Since you're calling setState() directly, I assume the first code snippet is part of a JFrame. In that case you're most probably sending the event dispatch thread to sleep for 5 seconds and thus prevent screen updates during that time.
Put the sleep into another thread or use a swing worker instead and call setState() on the EDT in the worker's callback method, since setState() is not labelled as thread-safe and calling it on a thread other than the EDT might result in unexpected behavior.
From the linked tutorial:
Some Swing component methods are labelled "thread safe" in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
Don't use Thread.sleep(5000);, that block EDT.
For that purposes you can use swing Timer, examine next example:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TestFrame extends JFrame {
private JLabel lbl;
public TestFrame() {
init();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void init() {
lbl = new JLabel(" ");
JButton setText = new JButton("setText");
setText.addActionListener(getActionListener());
add(lbl);
add(setText,BorderLayout.SOUTH);
}
private ActionListener getActionListener() {
return new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
lbl.setText("wait...");
Timer t = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
lbl.setText("");
setState(JFrame.ICONIFIED);
}
});
t.setRepeats(false);
t.start();
}
};
}
public static void main(String args[]) {
new TestFrame();
}
}
When dealing with Swing components you shuld not use threads like that. Launch your own SwingWorker instead.
public class MySwingWorker extends SwingWorker<Object, Object> {
#Override
public Object doInBackground() {
//your code here
//dont forget to repaint changed component or validate parent of it,
//if your text dont shows up.
return null;
}
}
you can also execute your own runnable via SwingUtilites
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//again your code here...
}
});
Consider the following code.
import edu.cmu.ri.createlab.terk.robot.finch.Finch;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class RobotControl extends JFrame {
public static void main (String args[]) {
RobotControl GUI = new RobotControl(); //GUI is the name of my object.
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setSize(300,300);
GUI.setVisible(true);
GUI.setTitle("RobotControl");
}
private JButton foward;
public RobotControl() { //constructor
setLayout (new FlowLayout());
foward = new JButton("foward");
add(foward);
ActionListener e = new event();
foward.addActionListener(e);
}
public class event implements ActionListener {
public void actionPerformed1(ActionEvent e){
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
}
Now consider the following code that would make my finch robot move foward for 10 seconds.
Finch myf = new Finch();
myf.setWheelVelocities(255, 255, 10000);
Now, my question is, would it be possible to execute the second piece of code as a result of clicking the foward button created on the GUI, from the first piece of code? If so how would i go about it. I have tried putting the finch code into the actionListener class but nothing happens. where am i going wrong. I need advice.
The short answer is, yes.
First, you need to maintain an instance of Finch as a instance variable...
public class RobotControl extends JFrame {
private Finch finch;
//...
}
You need to create an instance of Finch...
public RobotControl {
finch = new Finch();
}
Then in your ActionListener, you need to "communicate" with Finch
public void actionPerformed1(ActionEvent e){
myf.setWheelVelocities(255, 255, 10000);
}
The long answer, it's likely that you are going to have to issue multiple commands in sequence, the problem with this, is this process is likely to block the Event Dispatching Thread, preventing from responding to new incoming events and making it look like your application has "stopped"
While there are multiple ways you might alleviate this problem, if you don't need Finch to communicate with the UI (such as report status of motors or something), you could simply use a single threaded Executor of some kind and simply issue a sequence of commands via it.
If you need to provide feedback to the client UI, things become considerably more complicated...
Here is a sample code:
-------------------------
RobotControl.java
myrobot = new Finch();
foward = new JButton("foward");
add(foward);
forward.addActionListener(new ForwardButtonListener(myrobot));
-------------------------
ForwardButtonListener.java
public class ForwardButtonListener implements ActionListener {
Finch robotToControl;
public FowardButtonListener(Finch aRobot) {
robotToControl = aRobot;
}
public void actionPerformed (ActionEvent e) {
robotToControl.setWheelVelocities(255, 255, 10000);
}
}
-------------------------
I am a beginner in java and unfortunately I was stuck on this problem. In code:
NewJFrame.java :
public class NewJFrame extends JFrame {
public void showText() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jLabel1.setText("in show()"); //it does not work
System.out.println("in show()"); //it works
}
});
}
public NewJFrame() {
initComponents();
jLabel1.setText("start"); //it works
}
public static void main(String args[]) {
Timer timer = new Timer();
timer.schedule(new NewClass(), 1000, 2000);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
private javax.swing.JLabel jLabel1;
}
NewClass.java :
package newpackage;
import java.util.TimerTask;
class NewClass extends TimerTask {
public void run() {
System.out.println("in NewClass.run()"); //it works
new NewJFrame().showText();
}
}
I have a problem with the fact that the setText does not set jLabel1 when is called from timer thread. I tried to solve the problem using invokeLater(), but still does not work.
Thanks for your help.
The JLabel is never added to any container. Why would it appear?
As general advice, don't extend frame, simply keep a reference and as mentioned by #Reimeus, use a Swing Timer.
You are creating a new instance of NewJFrame in NewClass which never gets displayed:
new NewJFrame().showText();
You would need to pass the visible instance to NewClass for it to be updated.
However, better to use javax.swing.Timer rather than java.util.Timer to interact with Swing components. From How to Use Swing Timers:
In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread.
Also See: Concurrency in Swing
Try adding repaint() right after you set the text.
After changing the look of something on screen, you must always repaint the frame.
jLabel1.setText("in show()"); //it does not work
repaint(); //now it works
System.out.println("in show()"); //it works