0

I'm implementing a javax.swing.timer to call a synchronous operation on a GUI. However, that operation takes some time to finish and I'd like to provide an abort option to that timer call. Is that possible?

Thx!

import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Iterator;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.JTextField;
import org.omg.CosNaming.IstringHelper;


public class vtm extends JPanel implements ActionListener{

    private JFrame frame;
    private String children[];
    private ConsoleApp hawk[];
    public static String data[][];
    public Timer timer;
    private int count1, count2;
    private int i;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    vtm window = new vtm();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public vtm() {
        timer = new Timer(25000, this);
        //timer.setInitialDelay(190);
        timer.start();
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {

        frame = new JFrame("VTM");
        frame.setSize(1024, 720);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        JLabel lblNewLabel_1 = new JLabel("");
        lblNewLabel_1.setIcon(new ImageIcon("config.png"));
        lblNewLabel_1.setBounds(970, 0, 51, 55);
        frame.getContentPane().add(lblNewLabel_1);
        lblNewLabel_1.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                config x = new config();
                x.main(null);
                timer.stop();
                frame.dispose();
            }
            });

        JLabel lblNewLabel = new JLabel("");
        lblNewLabel.setIcon(new ImageIcon("bg.png"));
        lblNewLabel.setBounds(0, 0, 1024, 720);
        frame.getContentPane().add(lblNewLabel);


        String dir = System.getProperty("user.dir");

        File df = new File(dir);

        FilenameFilter fi = new FilenameFilter(){
            public boolean accept(File df, String name){
                return name.startsWith("D-");
            }
        };

        children = df.list(fi);
        hawk=new ConsoleApp[children.length];

        EventQueue.invokeLater(new Runnable(){
            public void run(){

                int count1 = 0; count2 = 0;

                for(i=0;i<children.length;i++)
                {


                hawk[i]=new ConsoleApp(children[i]);

                Iterator<String> it = hawk[i].p.iterator();

                System.out.println("Hi:"+hawk[i].p.size());

                while(it.hasNext())
                {
                    hawk[i].call(it.next());

                    if(count1 == 3)
                    {
                        count2++;
                        count1=0;
                    }

                    System.out.println("Look: " + hawk[i].l.getText().length());
                    hawk[i].l.setBounds((60 + 270*count1) + ((260-(hawk[i].l.getText().length()*7))/2), (70+(count2*60)), 260, 62);
                    hawk[i].c.setBounds(50 + 270*count1, (70+(count2*60)), 273, 62);
                    frame.getContentPane().add(hawk[i].c,0);
                    frame.getContentPane().add(hawk[i].l,0);

                    count1++;
                }
            }
            }
        });
    }

    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("lol");

        EventQueue.invokeLater(new Runnable(){
                public void run(){

                    int count1 = 0; count2 = 0;

                    for(i=0;i<children.length;i++)
                    {


                    hawk[i]=new ConsoleApp(children[i]);

                    Iterator<String> it = hawk[i].p.iterator();

                    System.out.println("Hi:"+hawk[i].p.size());

                    while(it.hasNext())
                    {
                        hawk[i].call(it.next());

                        if(count1 == 3)
                        {
                            count2++;
                            count1=0;
                        }

                        hawk[i].l.setBounds((60 + 270*count1) + ((260-(hawk[i].l.getText().length()*7))/2), (70+(count2*60)), 260, 62);
                        hawk[i].c.setBounds(50 + 270*count1, (70+(count2*60)), 273, 62);
                        frame.getContentPane().add(hawk[i].c,0);
                        frame.getContentPane().add(hawk[i].l,0);

                        count1++;
                    }
                }
                }
            });


    }


}
Ahmed Farid
  • 127
  • 1
  • 11
  • Why dont you add a little code? – Mohayemin Jul 18 '12 at 11:46
  • Done. Although I believe my question is sort of general and not specific to my code. Ignore the stupid coding mistakes plz! Code clean up is not done yet – Ahmed Farid Jul 18 '12 at 12:02
  • Ah... i asked for a **little** code. An [sscce](http://sscce.org/) more specifically. I think I will check that letter. – Mohayemin Jul 18 '12 at 12:09
  • sorry! That's why I didn't post it at first :$ – Ahmed Farid Jul 18 '12 at 12:18
  • If code cleanup is not done, do it before you post it. Why should we have to go through that whole code mess. If you cannot spare that time, why would we invest our time in your problem ? – Robin Jul 18 '12 at 21:23

3 Answers3

2

You actionPerformed triggers a Runnable, which I assume is what takes a long time and what you would like to abort. Inside the Runnable's run method you have two loops, for(i=0;i<children.length;i++) and while(it.hasNext()). If you add a stopping condition to these loops, you can make the Runnable finish early by controlling that condition from outside.

For example, add a field abort to vtm and change the two loops to for(i=0;i<children.length && !abort;i++) and while(it.hasNext() && !abort) respectively. You can now set abort to true and the Runnable will stop the next time it tries to loop again.

Jacob Raihle
  • 3,720
  • 18
  • 34
  • I think you are referring to the `volatile boolean` trick, right? Either way, my button click doesn't respond until the Runnable is done, so no effective changing of `abort` takes places AFAIK. Is there a way to get over that? – Ahmed Farid Jul 18 '12 at 12:36
  • I eventually merged your idea with the fact I switched my operations to threads. Although not successful yet (Due to an API exception still trying to get around whenever I trigger an `abort` flag), but your idea was the most suitable in my case. Thanks! – Ahmed Farid Jul 19 '12 at 06:38
2

Use a Swingworker instead of your Runnable, this is how you implement a canceling mechanism: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/cancel.html

Also see this question: How do I use SwingWorker in Java?

Community
  • 1
  • 1
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
0

I'm implementing a javax.swing.timer to call a synchronous operation on a GUI. However, that operation takes some time to finish and I'd like to provide an abort option to that timer call. Is that possible?

If you want to provide UI to your user to cancel that Runnable which you posted on the Event Dispatch Thread (EDT) while it is running, then no, it is not possible.

The moment your Runnable code starts executing, your UI will be unresponsive as the UI thread (the EDT) is occupied with your Runnable. So any Cancel button or whatever interface you had in mind will not react on any clicks until the Runnable is finished.

You can cancel it before it starts running, but a better investment of your time might be to investigate whether you really have to perform heavy work on the EDT (for which normally the answer is no). It would be better to do all the heavy calculations/operations on a worker Thread, and update the UI during/afterwards. The SwingWorker class was designed for this, and many examples of its usage can be found online (in the javadoc, the official Swing tutorials and on this site)

Robin
  • 36,233
  • 5
  • 47
  • 99
  • `SwingWorker` is definitely a promising candidate, but it meant modifying other classes to a great extent. That was not an option for the time being sadly. – Ahmed Farid Jul 19 '12 at 06:48