Do Java Swing action on specified Date - java

I'm trying to create a program which has two options:
- Do specific task after countdown (in minutes).
- Do specific task on the date selected.
Both are using jSpinners however, I don't know how to do the action on the specific date, here's the code below, thank you in advance!
protected Object doInBackground() throws Exception {
Timer t = new Timer(0, new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
//Checking state of CheckBoxes (one cancels the other)
if(jCheckBox2.isSelected()) {
try {
int delay =(int) jSpinner2.getValue();
jCheckBox1.setSelected(false);
Thread.sleep(delay*60000); //To delay the code from miliseconds to minutes
} catch (InterruptedException ex) {
Logger.getLogger(App_Gui.class.getName()).log(Level.SEVERE, null,
ex);
}
}
else if (jCheckBox1.isSelected()) {
Date delay2 = (Date) jSpinner1.getValue();
jCheckBox2.setSelected(false);
Thread.sleep(delay2); //What should I put here instead of Thread.sleep()???????
}
//If all is right, start the timer
t.start();
t.setRepeats(false);
//Popup dialog
JDialog dialog = new JDialog();
dialog.setLocation(700, 300);
dialog.setSize(600, 400);
dialog.setVisible(true);
//Speed of color changing
try {
Thread.sleep(jSlider1.getValue());
} catch (InterruptedException ex) {
Logger.getLogger(App_Gui.class.getName()).log(Level.SEVERE, null,
ex);
} //Setting the color
dialog.getContentPane().setBackground(jLabel2.getBackground());
dialog.setModal(true);
Assignment_Tajmer_Aplikacija.f.setVisible(false);
return null;
}
protected void done() {
System.out.println("Done!");
}
};
sw.execute();
}
private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {
// TODO add your handling cosadde here:
jSlider1.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
//System.out.println(source.getValue());
}
});
}

You have 2 choices:
You compute time difference in milliseconds between current date and target date. So you can start the swing timer. Something like myDate.getTime() - Sytem.currentTimeMillis() (it's probably not always correct)
You use a Library which do it for you (for example Quartz). In this case you need to synchronize your job with the Swing thread using the method SwingUtilities.invokeLater(Runnable).
And never use Thread.sleep() in a Swing application. Start a timer instead.

Related

Java: Thread.sleep mousepress delay

I've been trying to create an autoclicker in java using jnativehook.
It works fine, even compiles and runs. My problem is using Thread.sleep to try and add a delay between clicks:
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
If I were to input a delay of 0 it will function fine. But given no delay it will click too fast.
When I add a delay it will click fine but, when I release the trigger key it will keep clicking for a few seconds given the time it's been clicking. A delay of 0 will not do this however.
Full code:
public class App implements NativeKeyListener{
private JPanel panel1;
private JTabbedPane tabbedPane1;
private JButton spoilerButton;
private JSlider slider1;
private JSlider slider2;
//Removed irrelevant code...
static Robot bot;
static {
try {
bot = new Robot();
} catch (Exception e) {
e.printStackTrace();
}
}
static boolean pressed;
public void click() throws InterruptedException {
try {
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
e.printStackTrace();
}}
#Override
public void nativeKeyPressed(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode()) == "Delete") {
pressed = true;
while (pressed){
try {
click();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}}
#Override
public void nativeKeyReleased(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode())=="Delete"){
pressed=false;
}}
#Override
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
JFrame frame = new JFrame("Autoclicker");
frame.setContentPane(new App().panel1);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400,148);
frame.setResizable(false);
try{GlobalScreen.registerNativeHook();
} catch (Exception e){
System.exit(1);}
GlobalScreen.addNativeKeyListener(new App());
}
}
Looks like the method nativeKeyPressed() gets called continuously when you keep pressing the trigger key. This results in several calls to click() method (assuming it's multi threaded) and due to the sleep() between mouse press and release (mouse click is complete when released) this can happen.
Hence you can try two options depending on the root cause:
1. move the sleep() call after mouse released. If the nativeKeyPressed gets called concurrently this won't work.
2. Use a different thread to execute the click() method when trigger is pressed. In this case, you may need to submit a Runnable object to your thread each time with the 'pressed' check and click() call in it. This will ensure it won't run after pressed becomes false.

How to stop a timer

I have the following action performed method
public void actionPerformed(ActionEvent e) {
Timer timer = new Timer();
Object source = e.getSource();
String stringfromDate = tffromDate.getText();
String stringtoDate = tftoDate.getText();
if (source == button) {
// auto refresh begins
int delay = 0; // 0 seconds startup delay
int period = 7000; // x seconds between refreshes
timer.scheduleAtFixedRate(new TimerTask()
{
#Override
// i still have to truly understand what overide does however
// netbeans prompted me to put this
public void run() {
try {
getdata(stringfromDate, stringtoDate);// run get data
// method
} catch (IOException | BadLocationException ex) {
Logger.getLogger(JavaApplication63.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}, delay, period);
}
if (source == button1) {
timer.cancel();
textarea.setText("");
}
}
I have 2 buttons on my GUI one called get information(button) and another called clear information (button1).
I cant seem to get my clear information(button1) to stop the timer and clear the text area so that a new search can be performed. I just cant seem to get this to stop help appreciated.
Consider these changes to your code. Mainly the code does these things differently:
Pull up the declaration of your timer into the class, so that the same timer started before can be cancelled later.
only create a new timer if the start-button was pressed.
//Pulled up for access to make canceable .
protected Timer timer;
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
String stringfromDate = tffromDate.getText();
String stringtoDate = tftoDate.getText();
if (source == button) {
//Stop existing one before creating new.
if(timer != null) {
timer.cancel();
}
//Now make new
timer = new Timer();
// auto refresh begins
int delay = 0; // 0 seconds startup delay
int period = 7000; // x seconds between refreshes
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
getdata(stringfromDate, stringtoDate);// run get data
// method
} catch (IOException | BadLocationException ex) {
Logger.getLogger(JavaApplication63.class.getName()).log(Level.SEVERE, null, ex);
}
}
}, delay, period);
}
if (source == button1) {
//NULLCHECK
if(timer != null) {
timer.cancel();
}
textarea.setText("");
}
}

How to get user edited value of a JFormattedTextField that is updated 3 times/sec by a Swing Timer?

I have a JFormattedTextField component with an Integer value that is updated 3 times in a second when it doesn't have focus.
For updating the value I use Swing Timer.
I want to make it possible for user to edit its value(to update some value in the model) but I know that the value of a JFormattedTextField isn't updated every time it loses the focus. so it's not wise to change the model attributes in the lostFocus event and on the other hand when it loses the focus its value can be changed by the updater module which makes the situation more difficult.
It is clear that I can't use the propertyListener neither, because the value is updated 3 times in a second!
Now I wonder how I will be able to update the variable on place profiting JFormattedTextField capabilities and let updater update my JFormattedTextField when it doesn't have focus! Is it possible or I must use an inputDialog instead? How?
For example in the following code when I change the field value to 200 in the GUI and then click on the JFrame to make it lose focus the value printed in the console isn't 200. It's a great random value that was previously in the field.
public class SwingTimerFormattedTextFieldTester {
public static void main(String... args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 300, 200);
final JFormattedTextField field = new JFormattedTextField(new Long(100));
field.setColumns(20);
frame.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
frame.requestFocus();
e.consume();
}
});
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(field);
frame.setVisible(true);
Timer timer = new Timer(330, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(!field.hasFocus()){
field.setValue(ThreadLocalRandom.current().nextLong());
}
}
});
timer.start();
field.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
field.setBackground(Color.CYAN);
}
#Override
public void focusLost(FocusEvent e) {
field.setBackground(Color.WHITE);
System.out.println(String.valueOf((Long)field.getValue()));
}
});
frame.requestFocus();
}
}
What if you commit the edit to the JFormattedTextField on focus lost?
#Override
public void focusLost(FocusEvent e) {
try {
if (field.isEditValid()) {
field.commitEdit();
}
} catch (ParseException e1) {
e1.printStackTrace();
}
field.setBackground(Color.WHITE);
System.out.println(String.valueOf((Long) field.getValue()));
}

Swing: Enabling Buttons With Delay

private void OptionsActionPerformed(java.awt.event.ActionEvent evt)
{
// After clicking on button X, I want 4 other buttons to show up
// in a sequential order
ButtonTrue();
}
public void ButtonTrue()
{
Audio_Options.setVisible(true);
letsSleep();
Control_Options.setVisible(true);
letsSleep();
Display_Options.setVisible(true);
letsSleep();
Network_Options.setVisible(true);
}
public void letsSleep()
{
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(MainMenu.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have 4 buttons. I want them to appear in a sequential order such as :
Button1 - 10seconds - Button2 - 10 seconds - Button3 - 10seconds - Button 4
Problem: Whenever I call the function "ButtonTrue()", they all appear together after waiting 30 seconds. What can cause this problem to occur?
don't use Thread.sleep(int) for Swing JComponent, because blocking current EDT
you have look at Swing Timer
You should use different Threads for this:
javax.swing.Timer timer = new Timer(10000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Update the progress bar...
Control_Options.setVisible(true);
timer.stop();
}
});
timer.start();
Your buttons have to be final to be in scope for the anonymous ActionListener.
I think the problem is that all setVisble invocations are within one thread, which isn't EventDispatchThread. You could try calling:
if(EventQueue.isDispatchThread()) {
ButtonTrue();
} else {
EventQueue.invokeAndWait(new Runnable() {
ButtonTrue();
});
}

Why is it so hard to stop a thread in Java?

I've come again in one of THOSE situations where it is just impossible to stop/destroy/suspend a thread. .interrupt() doesn't do the trick and .stop() and .suspend() are deprecated.
Very simple example:
public class TimerThread extends Thread {
private JPanel colorPanel;
public TimerThread(JPanel colorPanel) {
this.colorPanel = colorPanel;
}
public void run() {
while (true) {
try {
Thread.sleep(1000);
colorPanel.repaint();
} catch (Exception ex) {
//do Nothing
}
}
}
}
What this does is repaint a certain JPanel every second to change its colour. I want to start and stop the thread like this from another class:
timer = new Thread(new TimerThread(colorPanel));
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.interrupt();
}
});
Obviously (?) this doesn't work... I know I could use a Timer, a SwingWorker or declare the timer as timer = new TimerThread(colorPanel); and use a boolean instead of "true" in the run method, but I've been asked to declare timer as a "Thread" and nothing else.
To my surprise (or is this that stupid?), even this didn't work:
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer = new Thread(new TimerThread(colorPanel));
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.interrupt();
timer = null;
}
});
So my question is simple: How do you make threads Start/Pause/Resume/Stop in Java?
when you get an interrupt you should start the cleanup and return a.s.a.p. (or at the very least reset the interrupted status)
while (true) {
try {
Thread.sleep(1000);
colorPanel.repaint();
} catch(InterruptedException e){//from sleep
return;//i.e. stop
} catch (Exception ex) {
//do Nothing
}
}
another way is to check Thread.interrupted() in the condition (but you'll need to reset the interrupted status in the catch of InterruptedException
however in swing you can use javax.swing.Timer to let an event run every so often and stop that with the api of that
javax.swing.Timer timer = new Timer(1000,new ActionListener() {
public void actionPerformed(ActionEvent e) {
colorPanel.repaint();
}
});
timer.setRepeats(true);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
Try this:
public class TimerThread extends Thread {
private volatile boolean stop = false;
private JPanel colorPanel;
public TimerThread(JPanel colorPanel) {
this.colorPanel = colorPanel;
}
public void stopTimer() {
stop = true;
}
public void run() {
while (stop == false) {
try {
Thread.sleep(1000);
colorPanel.repaint();
} catch (Exception ex) {
//do Nothing
}
}
}
}
// Why new Thread(new TimerThread(...))?
// timer = new Thread(new TimerThread(colorPanel));
timer = new TimerThread(colorPanel)
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stopTimer();
}
});
Also have a look at here to see how you can replicate stop now that it's deprecated.
You make them co-operate, basically. You have some shared flags to let them see what they should be doing, and whenever you would sleep, instead you wait on some shared monitor. Then when you want to control the thread, you set the appropriate flag and notify the monitor so that if the thread was waiting, it will wake up and notice that it should suspend/stop/whatever. Obviously you need to take the normal sort of care around shared state, using volatile variables, Atomic* objects or locking to make sure that every thread sees the updates made by every other thread.
Anything non-cooperative is risky due to the chance of corrupting state half way through an operation.
It is dangerous to stop threads pre-emptively. Doing so leads to deadlocks, resource leaks and so on. Instead you should use a cooperative signaling mechanism.
Signal to the thread that you want it to stop, and then wait for it to do so. The thread should regularly check whether it needs to stop and react accordingly.
Instead of looping while (true), you should loop while the thread is not interrupted:
#Override public void void() {
// some kind of initialization...
while (!Thread.currentThread().isInterrupted()) {
try { ...
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // ensure interrupt flag is set
}
}
// some kind of cleanup
}
If InterruptedException is not thrown by anything inside your while block, either you don't use blocking operations (and simply calling Thread.interrupt() on this thread would stop it the next iteration) or you use some blocking calls that are not well behaved (there are many such examples in the JCL itself!).
The correct way to do this is indeed to have a variable that determines when the Thread should be stopped, exiting from its run method. You can find more information about how to do this properly here
With this solution you won't get "instantaneous" updates that you could get with wait/notify or interrupt, but if you don't mind the fraction of a second delay, it should do the job.
volatile boolean stopped = false;
volatile boolean paused = false;
pauseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
paused = true;
}
});
resumeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
paused = false;
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopped = true;
}
});
... TimerThread
public void run() {
while (stopped == false) {
try {
Thread.sleep(1000);
if (stopped)
break;
if (!paused)
colorPanel.repaint();
} catch (Exception ex) {
//do Nothing
}
}
}

Categories