I have a process that shows confirm messages from JOptionPane. This process is called from SwingUtilities.invokeLater(runnable) that is inside an Actionlistener for a JMenuItem. The code for the runnable is this:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
MyClass c=new MyClass(file)
try {
c.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
this.finalize();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
In MyClass there's this method:
private boolean userInput(){
String message="yes or no?";
JCheckBox checkbox = new JCheckBox("Do this for all.");
Object[] params={message,checkbox};
int n=JOptionPane.showConfirmDialog(null,params,"message",JOptionPane.YES_NO_OPTION);
boolean answer=(n==JOptionPane.YES_OPTION)?true:false;
if(checkbox.isSelected()){
nextQ=false;
nextA=answer;
}
return answer;
}
which is called many times. When a JOptionPane message is displayed, I click its button(yes/no), but the message won't disappear until the next message is displayed. What might be the problem? Does this has to do with the method invokeLater ?
I found the way to solve this. I had to create a new Thread inside the SwingUrtilities.invokeLater method. This is the new code:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
Thread t=new Thread(new Runnable(){
MyClass c=new MyClass(file)
public void run(){
c.start();
}
});
t.start();
}
});
Related
Can't figure this one out. Using worker or invokeLater, the UI still freeze. After each file is downloaded, I want a JList to be updated. But the JList will only update after the tread returns.
Here is the code:
public class MyUi extends javax.swing.JFrame{
...
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){
SwingUtilities.invokeLater(new Runnable() {
//To get out of the event tread
public void run() {
dl();
}
});
}
private void dl(){
...
//ini and run the download class
Download myDownload = new Download();
myDownload.doDownload(myDlList);
}
public void updateJlist(String myString){
myModel.addElement(myString);
jList1.repaint();
}
}
public class Download{
...
public void doDownload(String[] fileName){
for(int i=0; i<fileName.length; i++){
...//download action...
//for my jList1 to be updated after each file.
MyUi.updateJlist(fileName[i]);
}
}
}
Any example would help.
invokeLater does exactly the opposite of what you expect it to do - it runs operations on the EDT, which explains the behaviour.
Download the file on a background thread and wrap just updateJlist() in a Runnable.
SwingWorker would be more reliable.
Addendum: As #mre notes, SwingWorker also makes it easy to report interim results, as shown here.
I have create a WorkerThread class which take care of Threads and GUI current/main thread . i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look.
/** * Action Event * * #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */
public void actionPerformed(ActionEvent ae) {
log.info("actionPerformed begin..." + ae.getActionCommand());
try {
if (ae.getActionCommand().equals(btnStart.getText())) {
final int portNumber = 9990;
try {
WorkerThread workerThread = new WorkerThread(){
public Object construct(){
log.info("Initializing the Server GUI...");
// initializing the Server
try {
xxxServer = new XXXServer(portNumber);
xxxServer.start();
btnStart.setEnabled(false);
} catch (IOException e) {
// TODO Auto-generated catch block
log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
e.printStackTrace();
}
return null;
}
};workerThread.start();
} catch (Exception e) {
log.info("actionPerformed() Start button ERROR..." + e.getMessage());
e.printStackTrace();
}
} else if (ae.getActionCommand().equals(btnStop.getText())) {
log.info("Exit..." + btnStop.getText());
closeWindow();
}
} catch (Exception e) {
log
.info("Error in ServerGUI actionPerformed==="
+ e.getMessage());
}
}
here is my exemple of making a circular loading bar with Jlayer but now the layer start and stop after the execution of the btnLoad.addActionListener() and stop after a while of determinated timer (4000) so my problem that I need it to start when I click the button load
and stop after complete the loading of the file !!!
final WaitLayerUI layerUI = new WaitLayerUI();
jlayer = new JLayer<JPanel>(this, layerUI);
final Timer stopper = new Timer(4000,new ActionListener() {
public void actionPerformed(ActionEvent ae) {
layerUI.stop();
}
});
stopper.setRepeats(false);
if (!stopper.isRunning()) {
stopper.start();
}
btnLoad.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
layerUI.start();
DataManager dataManager = new DataManager();
try {
dataManager.loadFromFile("C:/Users/*****PC/Downloads/****.csv");
} catch (Exception e) {
e.printStackTrace();
}
}
}
);
You should load the file on another Thread and not the Event Dispatch Thread. Assuming your loadFromFile method blocks until it loads the file, you can then hide the layer, but you must hide on the Event Dispatch Thread and not the new Thread you started for loading the file.
Remove your timer and replace your try block with this:
try {
new Thread(new Runnable(){
public void run() {
dataManager.loadFromFile("C:/Users/*****PC/Downloads/****.csv");
EventQueue.invokeLater(new Runnable(){
public void run() {
layerUI.stop();
}
});
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
This question already has answers here:
Stopping a Thread in Java? [duplicate]
(3 answers)
Closed 9 years ago.
I am trying to create a thread for a specific task to run in another class. The thread is starting the task but when I try to stop the thread, it is not stopping. The thread continues till the loop. Could you please help me out.
Thread Class:
package com.development;
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.JPanel;
public class ThreadExample extends JFrame {
MyThread mt;
Thread th;
ThreadExample(){
JPanel p1 = new JPanel();
p1.setPreferredSize(new Dimension(400,400));
JButton b1 = new JButton("Start");
JButton b2 = new JButton("Stop");
b1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
mt = new MyThread();
th = new Thread(mt);
th.start();
}
});
b2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
th.interrupt();
}
});
p1.add(b1);
p1.add(b2);
this.getContentPane().add(p1);
this.pack();
this.setVisible(true);
}
public static void main(String arg[]) {
ThreadExample mt = new ThreadExample();
mt.setVisible(true);
}
public class MyThread implements Runnable{
private volatile boolean runnable=true;
DisplayMsg dm = new DisplayMsg("Cycle");
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
// TODO Auto-generated method stub
dm.show();
}
}
}
}
DisplayMsg class:
package com.development;
public class DisplayMsg {
private String dispMsg;
private boolean runnable;
DisplayMsg(String dispMsg){
this.dispMsg=dispMsg;
}
public void show() {
for(int t=0;t<100;t++) {
try {
System.out.println(dispMsg + t);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Your DisplayMsg class loops for 100 seconds, and ignores interrupts. Indeed, when Thread.sleep() is interrupted, it resets the interrupt status, then throws an InterruptedException. Since you ignore the InterruptedException, the thread continues as if nothing happened.
public void show() {
for(int t=0;t<100;t++) {
try {
System.out.println(dispMsg + t);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Don't ignore interrupts:
public void show() {
for(int t=0;t<100;t++) {
try {
System.out.println(dispMsg + t);
Thread.sleep(1000);
} catch (InterruptedException e) {
// re-interrupt the thread and stop looping
Thread.currentThread().interrupt();
return;
}
}
}
A much simpler design which achieves what you need is the following:
public class MyThread implements Runnable{
DisplayMsg dm = new DisplayMsg("Cycle");
#Override public void run() {
try { while(true) dm.show(); }
catch (InterruptedException e) { }
}
}
public class DisplayMsg {
...
public void show() throws InterruptedException {
for(int t=0;t<100;t++) {
System.out.println(dispMsg + t);
Thread.sleep(1000);
}
}
}
This will simply let the InterruptedException propagate and end MyThread, with no effort on your own.
When you catch the InterruptedException in your DisplayMsg class, the interrupted flag is reset.
It's fine to catch the exception, but if you need to subsequently know if the thread has been interrupted, you need to reset the flag by interrupting again with Thread.currentThread.interrupt(); in that catch block and break out of the loop / return.
I believe what is happening is that you need to be checking !Thread.currentThread().isInterrupted() before each sleep. You are calling show() in the method which will iterate for 100 seconds only then will the your while loop check to see if the thread is interrupted. Move your check for interrtuped to your show method and see if it sees the interrupted flag. As per the next answers you should also set the Thread interrupted flag when you catch the InterruptedException.
In my GUI I have a PDF file creation operation. The operation can take up to 10-15 seconds to complete. When I start the operation, I attach a listener to it. The listener changes the cursor and disables the GUI, until the operation completes.
I would also like to add a progressbar, so the users will have a idea when it is going to complete.
Created a method startProgressBar() and called it from the start of the operation method.
See Below:
private void startSavePdfOperation() {
startProgressBar();
saveOp = new AplotSaveOperation(appReg.getString("aplot.message.SAVETOPDF"), "PDF", session);
saveOp.addOperationListener(new MyOperationListener(this) {
startProgressBar Method - See Below:
public void startProgressBar() {
Shell shell = new Shell(getShell());
shell.setSize(260, 120);
final ProgressBar bar = new ProgressBar(shell, SWT.SMOOTH);
bar.setBounds (20, 20, 200, 20);
shell.open();
final int maximum = bar.getMaximum();
new Thread(new Runnable() {
public void run() {
for (final int[] i = new int[1]; i[0] <= maximum; i[0]++) {
try {Thread.sleep (100);} catch (Throwable th) {}
if (Display.getDefault().isDisposed()) return;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (bar.isDisposed ()) return;
bar.setSelection(i[0]);
}
});
}
}
}).start();
The code above created the ProgressBar. The issue is that the operation would end well before the progressbar indicator was close to ending.
Question: Is this because in the method I am creating a new thread and the indicator is updating according to the new thread and not the operation thread?
Question: Is it possible to create a new thread that watches the GUI thread and updates the progressbar accordingly?
Read a article suggesting using ProgressMonitorDialog with IRunnableWithProgress.
Method startProgressBar using ProgressMonitorDialog - see below:
public void startProgressBar() {
ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
try {
dialog.run(true, true, new IRunnableWithProgress(){
public void run(IProgressMonitor monitor) {
monitor.beginTask("Some nice progress message here ...", 100);
** getThread(); **
monitor.done();
}
});
}
catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void getThread() {
new Thread etc.. etc...
}
It seems that it will have the same issues with threading and updating as the code above.
Question: So now I am thinking can I just add or update the ProgressBar to my existing Listener
OperationListener Code - see below:
public abstract class MyOperationListener implements InterfaceAIFOperationListener {
AplotCreatePDFDialog w = null;
public MyOperationListener(AplotCreatePDFDialog win) {
w = win;
}
public void startOperation(String startMessage) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_WAIT));
w.recursiveSetEnabled(getShell(), getShell().getEnabled());
w.getShell().setEnabled(!getShell().getEnabled());
}
});
}
public void endOperation() {
try {
endOperationImpl();
}
finally {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW));
w.recursiveSetEnabled(getShell(), true);
w.getShell().setEnabled(!getShell().getEnabled());
w.close();
}
});
}
}
abstract protected void endOperationImpl();
} // end class MyOperationListener
Thanks for any help you can give me with this.
EDIT
Baz, your answer below is exactly what the question asked, so thank you for answering.
But I am starting to think that what I am trying to do is not possible.
When my operation starts, I wanted the progress bar indicator to start and when my operation ended I wanted the indicator be at the end and the monitor would close.
I thought there might bee a way to use my listener to add the progressbar. Something like the following.
public void startOperation(String startMessage) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
->monitor.beginTask("Creating PDF File(s)", IProgressMonitor.UNKNOWN);<-
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_WAIT));
w.recursiveSetEnabled(getShell(), getShell().getEnabled());
w.getShell().setEnabled(!getShell().getEnabled());
}
});
}
public void endOperation() {
try {
->monitor.worked(1);<-
endOperationImpl();
}
finally {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
w.getShell().setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_ARROW));
w.recursiveSetEnabled(getShell(), true);
w.getShell().setEnabled(!getShell().getEnabled());
->monitor.done();<-
w.close();
}
});
}
}
abstract protected void endOperationImpl();
} // end class MyOperationListener
But I am starting to see that the ProgressBar has to have some sort of measurement to display the indicator correctly.
I would be happy if the indicator just went back and forth and the monitor would close at the end of the operation.
Why not use ProgressMonitorDialog?
Here is a related answer from me showing a simple example.
This is what it looks like:
If you are not sure about the workload, use this code:
monitor.beginTask("Copying files", IProgressMonitor.UNKNOWN);
It will show the idle bar while running.
How do I exit my program from an actionlistener. I have two threads, thread1 and thread2. One thread is in actionlistener. but i want the other thread to exit this actionlistener and manage rest of the code.. How can I do it?
sendtkttgt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread thread1= new Thread(){
public void run(){
SendingLogictoTGT obj=new SendingLogictoTGT();
try {
try {
obj.main(null);
} catch (InterruptedException ex) {
}
} catch (IOException ex) {
// System.exit(1);
}
}
};
/*Thread thread2= new Thread(){
public void run(){
//I want to exit from this actionlistener
}
};
*/
thread1.start();
}
});
interrupt() would be your best choice.