Results 1 to 11 of 11
  1. #1
    Berkan is offline Member
    Join Date
    Nov 2008
    Posts
    4
    Rep Power
    0

    Default SwingWorker Problem

    Hello,

    I am a novice Java user and new to the forum. My swingworker problem is explained below.

    CASE:

    In order to simulate a lengthy computation, I created a hello.exe that prints

    "This is line 1
    This is line 2
    ...
    etc."

    60 times, while pausing a second between each line.
    (I have zipped and attached the simple hello.exe to the thread)

    AIM:
    I am trying to build a JFrame windows with a 'Compute' button that will start this computation and show the output in a JTextArea in real time with interim results. (Rather than freezing the window and giving the whole output at once when the .exe terminates)

    ATTEMPT:
    I know the solution requires the usage of SWINGWORKER and it should be quite similar to the Flipper.java example given in the SwingWorker tutorial on
    "java.sun.com/docs/books/tutorial/uiswing/concurrency/interim.html".

    However, I am rather confused about this "doInBackground" and "process" methods. In other words I do not know how to arrange the contents of ComputeTask class below. I wrote this code which does not work:


    Any help & advice will be great!
    ------------------------------------------------------------
    package progressdialog;

    import java.io.*;
    import java.awt.BorderLayout;
    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;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingWorker;

    public class Hello extends JPanel {

    JButton computeButton;
    JTextArea textArea;
    JScrollPane areaScrollPane;
    private ComputeTask computeTask;

    public Hello () {

    textArea = new JTextArea(" ");
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    areaScrollPane = new JScrollPane(textArea);
    areaScrollPane.setVerticalScrollBarPolicy(JScrollP ane.VERTICAL_SCROLLBAR_ALWAYS);
    areaScrollPane.setPreferredSize(new Dimension(500, 250));
    computeButton = new JButton ("Compute");
    computeButton.setEnabled(true);
    computeButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {

    (computeTask = new ComputeTask()).execute();
    }
    });

    add(computeButton,BorderLayout.PAGE_START);
    add(areaScrollPane, BorderLayout.CENTER);
    }


    // Tried to copy the SwingWorker structure and implement it to my exe running case. Could not achieve
    private class ComputeTask extends SwingWorker<Void, String> {
    String line;
    @Override
    protected Void doInBackground() throws IOException {

    Runtime r = Runtime.getRuntime();
    String s = "C:\\Documents and Settings\\msesen\\Desktop\\hello.exe";
    Process p;
    p = r.exec(s);
    InputStreamReader in = new InputStreamReader(p.getInputStream());
    BufferedReader br = new BufferedReader(in);

    while ((line = br.readLine()) != null) { publish (line); }
    throw new UnsupportedOperationException("Not supported yet.");
    }

    protected void process ( /*do not know what should go in here */) {
    textArea.setText(line);
    }
    }


    private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("Hello Concurrency Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E);
    frame.add(new HelloWindow());
    frame.pack();
    frame.setVisible(true);
    }

    public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
    createAndShowGUI();
    }
    });
    }

    public void actionPerformed(ActionEvent e) {
    throw new UnsupportedOperationException("Not supported yet.");
    }

    }

    ------------------------------------------------------------


    Thanks in advance for your time and sharing.

    Regards,
    Berkan
    Attached Files Attached Files

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    I didn't run your code as I don't as a rule run unknown exe's. But have you tried using a List<String> for your process method's parameter? Something like so is similar to what the tutorial uses
    Java Code:
        @Override
        protected void process(java.util.List<String> lines) 
        {
          for (String string : lines)
          {
            textArea.append(string + "\n");
          }
        }
    edit: corrected. It should be textArea.append, not textArea.setText
    Last edited by Fubarable; 11-22-2008 at 07:14 PM.

  3. #3
    Berkan is offline Member
    Join Date
    Nov 2008
    Posts
    4
    Rep Power
    0

    Default

    Hi Fubarable,

    Thank you. I have inserted the code in as recommended. Now the code is runnable. However when I run, what I get is still only the last line of the code ("This is line 60") after the .exe terminates .

    i.e. I do not see anything on my textArea exactly for a minute (during the countdown), then on the sixtieth second i see "This is line 60".

    Still not getting any interim results/updates during execution :( .

    ------------------------------------------
    package progressdialog;

    import java.io.*;
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.util.List;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.AbstractButton;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    //import progressdialog.ExeRunner;
    import javax.swing.SwingWorker;



    /**
    *
    * @author msesen
    */
    public class Hello extends JPanel {

    JButton computeButton;
    JTextArea textArea;
    JScrollPane areaScrollPane;
    private ComputeTask computeTask;

    public Hello () {

    textArea = new JTextArea(" ");
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    areaScrollPane = new JScrollPane(textArea);
    areaScrollPane.setVerticalScrollBarPolicy(JScrollP ane.VERTICAL_SCROLLBAR_ALWAYS);
    areaScrollPane.setPreferredSize(new Dimension(500, 250));
    computeButton = new JButton ("Compute");
    computeButton.setEnabled(true);
    computeButton.setToolTipText("Click this button to disable the middle button");
    computeButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {

    (computeTask = new ComputeTask()).execute();
    }
    });

    add(computeButton,BorderLayout.PAGE_START);
    add(areaScrollPane, BorderLayout.CENTER);
    }

    private class ComputeTask extends SwingWorker<Void, String> {
    String line;
    Runtime r = Runtime.getRuntime();
    String s = "C:\\Documents and Settings\\msesen\\Desktop\\hello.exe";
    Process p;

    @Override
    protected Void doInBackground() throws IOException {

    p = r.exec(s);
    InputStreamReader in = new InputStreamReader(p.getInputStream());
    BufferedReader br = new BufferedReader(in);

    while ((line = br.readLine()) != null) { publish (line); }
    throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void process(java.util.List<String> lines)
    {
    for (String string : lines)
    {
    textArea.setText(string + "\n");
    }

    }
    }


    private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("Hello Concurrency Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E);
    frame.add(new HelloWindow());
    frame.pack();
    frame.setVisible(true);
    }


    public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
    createAndShowGUI();
    }
    });
    }

    }

    ------------------------------------------

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Please see my correction above. You need to use the method append, not setText

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    for example:
    Java Code:
    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.JPanel;
    import javax.swing.JComponent;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingWorker;
    
    public class Fubar5b
    {
      private static final String[] STRINGS = 
      {
        "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"
      };
      private JPanel mainPanel = new JPanel();
      private JTextArea textArea = new JTextArea(10, 20);
    
      public Fubar5b()
      {
        JButton computeButton = new JButton("Compute");
        computeButton.addActionListener(new ComputeAction());
        mainPanel.add(computeButton);
        mainPanel.add(new JScrollPane(textArea));
      }
    
      public JComponent getComponent()
      {
        return mainPanel;
      }
      
      public void appendText(String text)
      {
        textArea.append(text);
      }
    
      private class ComputeAction implements ActionListener
      {
        public void actionPerformed(ActionEvent e)
        {
          final JButton source = (JButton)e.getSource();
          source.setEnabled(false);
          new SwingWorker<Void, String>()
          {
            private static final long SLEEP_DELAY = 200;
            private static final int REPEAT_TIMES = 5;
    
            @Override
            protected Void doInBackground() throws Exception
            {
              for (int i = 0; i < REPEAT_TIMES; i++)
              {
                for (int j = 0; j < STRINGS.length; j++)
                {
                  publish(STRINGS[j]);
                  Thread.sleep(SLEEP_DELAY);
                }
              }
    
              return null;
            }
            
            @Override
            protected void process(List<String> chunks)
            {
              for (String string : chunks)
              {
                appendText(string + "\n");
              }
            }
            
            @Override
            protected void done()
            {
              source.setEnabled(true);
            }
            
          }.execute();
          
        }
      }
      
      private static void createAndShowUI()
      {
        JFrame frame = new JFrame("Fubar5b");
        frame.getContentPane().add(new Fubar5b().getComponent());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args)
      {
        java.awt.EventQueue.invokeLater(new Runnable()
        {
          public void run()
          {
            createAndShowUI();
          }
        });
      }
    }

  6. #6
    Berkan is offline Member
    Join Date
    Nov 2008
    Posts
    4
    Rep Power
    0

    Default

    Thx again Fubarable.

    I changed setText to append, still no interim results.

    I believe the problem originates from my clumsy and erronous distribution of the exeRunning code

    ( p = r.exec(s);
    InputStreamREader in ...
    )

    into "doInBackground" and "process" methods.

    Since I could not quite get the algorithm from flipper.java I can not establish an analogy with my case and am just randomly plugging in my exerunning code into the SwingWorker methods.

    Berkan

  7. #7
    Sumuduboy is offline Member
    Join Date
    Mar 2009
    Posts
    2
    Rep Power
    0

    Default Solution to "SwingWorker Problem"

    Hi Berkan,

    The main problem is actually not in your Java code but in your "hello.exe".
    In its code, you probably have written print statements but have forgotten to flush the output once per line.

    I have attached a zip file containing both the modified Java source and a C source file that correctly does the flushing.

    Sumudu
    Attached Files Attached Files

  8. #8
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,458
    Rep Power
    20

    Default

    Aw c'mon, the question was asked nearly 4 months ago.

  9. #9
    Sumuduboy is offline Member
    Join Date
    Mar 2009
    Posts
    2
    Rep Power
    0

    Default

    It's better late than never, Darryl.Burke. :)

  10. #10
    cotarelo is offline Member
    Join Date
    Mar 2010
    Posts
    43
    Rep Power
    0

    Default I have a similar problem

    I have a similar problem, I am a bit newbie, and I am doing a swing gui interface for a Java program that showed the results on the command line on linux., I am trying to show all these results in a textarea, the problem is that the results come all at one time, and the program gets freezed whenever I press the "execute" button until all results are displayed. In the original program, the results were showed in the console line by line.

    This is a part of code which writes into the textarea:

    Java Code:
    for (;;) {
    
    			System.step();
    
    				if (step % SCREEN_INTERVAL == 0) {
    				step++;
    
                                    // output = output of program (each LiNE)
                                    output = String.format(
    						"%d\tA=%d\tBt=%d\tRsp=%d\tE=%d\t+=%d\t-=%d\tdr=%d\tF=%d\tFF=%d\t\tB=%d\tLV=%3.2f\n",step - 1, System.gC(), Stats.b, Stats.r, NS.gEC(), Stats.a, Stats.r, Stats.dr, Stats.f, Stats.ff, Stats.b, Stats.l());
    
    			//  output before the gui
                            //        System.out.println(output);
    
                            // Write into a output file (pw = PrintWriter)
    
                             pw.println(output);
    
    
                             // write output into the gui (TEXTAREA)
                             vst.jtxaConsole.append(output);
    
    
                                       Stats.reset();
    			} else
    				step++;
    		}
    I was reading that I need to do it with a Swingworker, but I am not sure where and how.

    Thanks

  11. #11
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Cotarelo: your question is important, and yes, the solution is to use a SwingWorker object, but I ask that you ask this question in its own thread, and I'm locking this one. Check out the Sun Java tutorial labeled "Concurrency in Swing". Again, if you need more help, please feel free to start your own thread for this question. Best of luck!

Similar Threads

  1. Replies: 3
    Last Post: 10-02-2008, 06:48 AM
  2. swingworker
    By musiigedeo in forum AWT / Swing
    Replies: 1
    Last Post: 07-26-2007, 01:59 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •