I'm making a program that, for the time being, just prints Printing... every half second. Here is my code:
package mainPackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Ticker {
public static void tick() {
System.out.println("Printing...");
}
public static void main(String args[]) {
ActionListener timerListener = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
tick();
}
};
Timer mainTimer = new Timer(500,timerListener);
mainTimer.start();
}
}
From my understanding the mainTimer object should be firing the event handled by timerListener every 500ms. When I execute this code nothing happens, am I missing something obvious?
Use swing timer under swing event dispatch thread:
public static void main(String args[]) {
ActionListener timerListener = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
tick();
}
};
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Timer mainTimer = new Timer(500,timerListener);
mainTimer.start();
}
});
}
If you don't plan on changing the GUI from the timer, consider using java.util.Timer
Related
The program hangs after trying to construct another instance of itself when I wait for the reference returned by the constructor to be set.
If I click on the button, the program will hang.
edit: removed silly second wait loop.
edit 2: change true to false when calling constructor. program seems to work now.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
public class Problem extends JPanel {
public Problem(boolean wait) {
frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
if(wait) try {
System.out.println("calling invoke and wait");
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
Problem.this.run();
}
});
} catch(InvocationTargetException|InterruptedException e) {
throw new RuntimeException(e);
}
else {
System.out.println("calling invoke later");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Problem.this.run();
}
});
}
}
public String title() {
return "title";
}
public void addContent() {
JButton button=new JButton("click");
add(button,BorderLayout.CENTER);
button.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent arg0) {
Runnable runnable=new Runnable() {
#Override public void run() {
System.out.println("before new "+Thread.currentThread());
problem=new Problem(false);
System.out.println("after new "+Thread.currentThread());
}
};
new Thread(runnable).start();
System.out.println("before first wait "+Thread.currentThread());
while (problem==null)
;
}
});
}
void run() {
frame.setTitle(title());
frame.getContentPane().add(this,BorderLayout.CENTER);
addContent();
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new Problem(false);
}
Problem problem;
public final JFrame frame;
private static final long serialVersionUID=1;
}
p1 = problem instance from main function
State 1: Creation - p1 is initialized. p1.problem is null
State 2: User clicks button. Eventually, in another thread, p1.problem is created. However, p1.problem.problem had never been initialized and won't be until the user clicks a button, which will never happen. I'm not sure what you're trying to do but it seems like your program is hanging on while (problem.problem==null);
I have problems with Java's Multi-Threading feature, so hopefully somebody can help me....
Here is my problem:
In the JPanel ExamplePanel which is located in the JFrame ExampleFrame I've added a ComponentListener which invokes the startPaint()-Method. This method should work in a new Thread. My Problem is that by resizing the window "former" Threads aren't closed, meanwhile new Threads are added....
So is there a way to resize the JPanel and to close at the same time the "old" threads, so that the number of threads is not growing, when I resize the JPanel?
I have tried something with a boolean exiter-variable, but it do not seemed to work...
here is the code:
package example;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Example2 {
public static void main(String[] args) throws InterruptedException {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new ExampleFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class ExampleFrame extends JFrame {
private static final long serialVersionUID = 1L;
ExamplePanel examplePanel = new ExamplePanel();
private Thread t=null;
private class ExamplePanel extends JPanel implements ComponentListener {
private static final long serialVersionUID = 1L;
#Override
public void componentHidden(ComponentEvent e) {
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentResized(ComponentEvent e) {
startPaint();
}
#Override
public void componentShown(ComponentEvent e) {
}
private void startPaint() {
t=new Thread(new Runnable() {
#Override
public void run() {
//System.out.println(Thread.currentThread().getName());
while (true) {
//System.out.println(Thread.activeCount());
}
}
});
t.start();
}
}
public ExampleFrame() {
examplePanel.addComponentListener((ComponentListener) examplePanel);
getContentPane().add(examplePanel);
}
}
if the calculations don't take long don't use an extra Thread.
if you need this extra Thread make sure that it doesn't run forever (no while (true) without returning at some point)
you can always interrupt your running Thread bfore creating the new one
if (t != null && t.isAlive()) {
t.interrupt();
}
and check in the while(true) loop if the Thread is interrupted
if (t.isInterrupted()) {
System.out.println("Thread ended");
return;
}
hope this helps
I was reading the documentation on swing timers, when I came across some information about ActionListeners. When further researched, all I could find is how to create an ActionListener attached to a JButton, etc. How can you create a plain ActionListener, not attached to anything?
My timer is not working correctly, and I thought it may be because I was incorrectly using the ActionListener.
Here is my code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class MyTimer {
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("testing");
}
};
public MyTimer() {
Timer timer = new Timer(10, al);
timer.start();
}
public static void main(String[] args) {
MyTimer start = new MyTimer();
}
}
An ActionListener is just an interface
You can create an stand alone version by implementing it and then instanstanting it....
public class MyActionHandler implements ActionListener {
public void actionPerformed(ActionEvent evt) {
// do something...
}
}
And sometime in the future...
MyActionHandler handler = new MyActionHandler();
Or you could create an anonymous instance....
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// do something...
}
};
Take a look at Interfaces for more details
How can you create a plain actionlistner, not attached to anything?
Loot at this:
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello World!");
}
};
// Using the listener with 2 seconds delay
java.swing.Timer timer = new java.swing.Timer(2000, listener);
timer.setRepeats(false);
// Start the timer
timer.start();
Try with this:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class MyTimer {
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("testing");
}
};
public MyTimer() {
Timer timer = new Timer(1000, al);
timer.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new MyTimer();
}
});
}
}
ive done some extensive searching on using threads in a loop and whilst I understand the concept how how seperate threads work, I still cant seem to grasp how to implement it in my simple application.
My application consists of a form with a text box. This textbox needs to be updated once ever iteration of a loop. It starts with the press of a button but the loop should also finish with the press of a stop button. Ive used a boolean value to track if its been pressed.
Here is my form code:
package threadtester;
public class MainForm extends javax.swing.JFrame {
public MainForm() {
initComponents();
}
private void RunButtonActionPerformed(java.awt.event.ActionEvent evt) {
ThreadTester.setRunnable(true);
ThreadTester example = new ThreadTester(2,this);
example.run();
}
private void StopButtonActionPerformed(java.awt.event.ActionEvent evt) {
ThreadTester.setRunnable(false);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainForm().setVisible(true);
}
});
}
public void setTextBox(String myString){
MainTextbox.setText(myString);
}
}
As you can see I have a button that is pressed. When the button is pressed this executes the code thats in a different class called ThreadTester. Here is the code for that class:
package threadtester;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadTester implements Runnable
{
int thisThread;
MainForm myMainForm;
private static boolean runnable;
// constructor
public ThreadTester (int number,MainForm mainForm)
{
thisThread = number;
myMainForm = mainForm;
}
public void run ()
{
for (int i =0;i< 20; i++) {
if(runnable==false){
break;
}
System.out.println("I'm in thread " + thisThread + " line " + i);
myMainForm.setTextBox(i + "counter");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE, null, ex);
}
} }
public static void setRunnable(Boolean myValue){
runnable = myValue;
}
public static void main(String[] args) {
MainForm.main(args);
}
}
as you can see the loop has been created on a seperate thread... but the textbox only updates after the loop has finished. Now as far as im aware in my MainForm I created a seperate thread to run the loop on, so I dont understand why its not running? Any guidence would be much appreciated, ive tried looking at examples on stack exchange but I cant seem to get them to fit into my implemntation.
With the recommendation suggested by Tassos my run method now looks like this:
public void run ()
{
for (int i =0;i< 20; i++) {
if(runnable==false){
break;
}
System.out.println("I'm in thread " + thisThread + " line " + i);
final String var = i + "counter";
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
myMainForm.setTextBox(var);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE, null, ex);
}
} }
In order for Tassos' answer to work, you actually have to create an new thread, which you did not do. Simply calling
ThreadTester example = new ThreadTester(2,this);
example.run();
is not enough, sice that just calls the run method from EDT. You need to do the following:
Thread t = new Thread(new ThreadTester(2,this));
t.start();
Please refer to Defining and Starting a Thread.
Also, you want modify the same field from two different threads (runnable), which is a bug. You should read more about java concurrency.
Change this line
myMainForm.setTextBox(i + "counter");
into
final String var = i + "counter";
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
myMainForm.setTextBox(var);
}
});
}
Why? Because you can't do UI work in non-UI threads.
The problem is that you are blocking the EDT (Event Dispatching Thread), preventing the UI to refresh until your loop is finished.
The solutions to these issues is always the same, use a Swing Timer or use a SwingWorker.
Here is an example of the usage of a SwingWorker:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class TestSwingWorker {
private JTextField progressTextField;
protected void initUI() {
final JFrame frame = new JFrame();
frame.setTitle(TestSwingWorker.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Clik me to start work");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
doWork();
}
});
progressTextField = new JTextField(25);
progressTextField.setEditable(false);
frame.add(progressTextField, BorderLayout.NORTH);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
protected void doWork() {
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
#Override
protected Void doInBackground() throws Exception {
// Here not in the EDT
for (int i = 0; i < 100; i++) {
// Simulates work
Thread.sleep(10);
publish(i); // published values are passed to the #process(List) method
}
return null;
}
#Override
protected void process(List<Integer> chunks) {
// chunks are values retrieved from #publish()
// Here we are on the EDT and can safely update the UI
progressTextField.setText(chunks.get(chunks.size() - 1).toString());
}
#Override
protected void done() {
// Invoked when the SwingWorker has finished
// We are on the EDT, we can safely update the UI
progressTextField.setText("Done");
}
};
worker.execute();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestSwingWorker().initUI();
}
});
}
}
Can any one tell me how a JButton appears[Fade in], after a short delay.I am working with Netbeans - drag and drop concept for all components.
Personally I would look at making a class that extends your JButton and overriding the paint method. Use both the JTimer to change the values of "setComposite()" (found in the graphics2D class) method over time.
Example of changing the composite in java:
AlphaComposite newComposite =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f)
g2d.setComposite(newComposite);
Here is the code that i found on which the above problem working.
import java.awt.Color;
import java.util.Timer;
import java.util.TimerTask;
public class delay extends javax.swing.JFrame {
Timer timer;
public delay(int seconds) {
initComponents();
jButton1.setVisible(false);
getContentPane().setBackground(Color.red);
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
}
class RemindTask extends TimerTask{
public void run() {
jButton1.setVisible(true);
timer.cancel();
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new delay(5).setVisible(true);
}
});
}
}