Avatar billede fredand Forsker
06. september 2012 - 20:57 Der er 6 kommentarer og
1 løsning

How to update a text from actionPerformed

Hello guys!

I think this is about some swing-thread-knowledge.
How ever.

I get a JButton, and a JTextField.

The idea is that when the user pushes the button, it will load a URL from a server.
But since that might take some time. I think it would be nice with to info messages in a textfield like:

public void actionPerformed(ActionEvent arg0)
{
  textField.setText("Loading started...");
  String page = loadUrl();
  textField.setText("...Loading done");
}

How ever, even dough the server some times takes several seconds to respond I just get "...Loading done" as info.

I guess this should be done in some other way.

All help is appreciated.

Best regards
Fredrik
Avatar billede arne_v Ekspert
06. september 2012 - 21:03 #1
Correct. When those lines are executed on the event thread things are done like:

1) textField.setText("Loading started...");
2)  String page = loadUrl();
3) textField.setText("...Loading done");
4) update screen

And that gives the observed result.

You need to call loadUrl in a separate thread, but still update textField on the event thread as Swing components are usualy not threadsafe.
Avatar billede arne_v Ekspert
06. september 2012 - 21:04 #2
Example:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class GuiPinger extends JFrame {
    private JTextField tf;
    private JTextArea ta;
    private JButton btn;
    public GuiPinger() {
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setTitle("Pinger");
        setLayout(new BorderLayout());
        tf = new JTextField();
        JPanel top = new JPanel();
        top.setLayout(new BorderLayout());
        top.add(new JLabel("Host: "), BorderLayout.WEST);
        top.add(tf, BorderLayout.CENTER);
        getContentPane().add(top, BorderLayout.NORTH);
        ta = new JTextArea();
        getContentPane().add(new JScrollPane(ta), BorderLayout.CENTER);
        btn = new JButton("Ping");
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ta.setText("");
                Thread t = new Thread(new Runnable() {
                    public void run() {
                        try {
                            Process p = Runtime.getRuntime().exec(new String[] { "ping", tf.getText() });
                            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                            String line;
                            while((line = br.readLine()) != null) {
                                final String line2 = line + "\n";
                                EventQueue.invokeLater(new Runnable() {
                                    public void run() {
                                        ta.append(line2);
                                    }
                                });
                            }
                            p.waitFor();
                        } catch (IOException e) {
                            JOptionPane.showMessageDialog(null, e.getMessage());
                        } catch (InterruptedException e) {
                            JOptionPane.showMessageDialog(null, e.getMessage());
                        }
                    }
                });
                t.start();
            }
        });
        getContentPane().add(btn, BorderLayout.SOUTH);
        setSize(800, 600);
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new GuiPinger();
                f.setVisible(true);
            }
        });
    }
}
Avatar billede arne_v Ekspert
06. september 2012 - 21:06 #3
The long running thing (here excuting an external ping command) are done in a thread.

When the thread need to update the GUI it uses  EventQueue.invokeLater, which will cause it to be done in the event thread.
Avatar billede arne_v Ekspert
06. september 2012 - 21:07 #4
Another example:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Paging extends JFrame implements ActionListener {
    private JTextField txt;
    private JButton btn;
    public Paging() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new BorderLayout());
        txt = new JTextField();
        txt.setText("");
        getContentPane().add(txt, BorderLayout.CENTER);
        btn = new JButton("Vis nyt billede");
        btn.addActionListener(this);
        getContentPane().add(btn, BorderLayout.SOUTH);
        this.setSize(300, 300);
    }
    public void load(String s) {
        txt.setText(s);
    }
    public void actionPerformed(ActionEvent ev) {
        if (ev.getSource() == btn) {
            T t = new T(this);
            t.start();
        }
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Paging f = new Paging();
                f.setVisible(true);
            }
        });
    }
}

class T extends Thread {
    private static int n = 0;
    private Paging pag;
    public T(Paging dn) {
        this.pag = dn;
    }
    public void run() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                pag.load("Nu viser vi billede af nogle pausefisk");
            }
        });
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                n++;
                pag.load("Nu viser vi et rigtigt billede nummer " + n);
            }
        });
    }
}
Avatar billede fredand Forsker
06. september 2012 - 22:13 #5
Hello Arne!

I followed you example and did it like:

    public void actionPerformed(final ActionEvent e)
    {
        textfield.setText"Loading started...");

                T t = new T("...loading done!");
                t.start();
        }

....

    class T extends Thread
    {
        String message;
        public T(String m)
        {
            message = m;
        }
        public void run()
        {
            loadUrl();
                       
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    textfield.setText(message);            }
            });
        }
    }

Seems to work fine!!
If you see anything bad or something I did not get right just let me know!

How ever "mange tak"!
My best regards, really good examples you provided!!
Btw give a svar so I can reward you!
Avatar billede arne_v Ekspert
07. september 2012 - 03:45 #6
I would probably let the thread write both messages to be consistent.

But that is style not function.
Avatar billede arne_v Ekspert
07. september 2012 - 03:45 #7
og svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester