Oprettet tor. d. 06. september 2012 kl. 20:57:13

fredand
fredand (8.560 point. Point ude: 330)

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

Skrevet tor. d. 06. september 2012 kl. 21:03:47| #1

arne_v
arne_v (1.048.588 point)
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.

Skrevet tor. d. 06. september 2012 kl. 21:04:58| #2

arne_v
arne_v (1.048.588 point)
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);
            }
        });
    }
}

Skrevet tor. d. 06. september 2012 kl. 21:06:12| #3

arne_v
arne_v (1.048.588 point)
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.

Skrevet tor. d. 06. september 2012 kl. 21:07:51| #4

arne_v
arne_v (1.048.588 point)
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);
            }
        });
    }
}

Skrevet tor. d. 06. september 2012 kl. 22:13:02| #5

fredand
fredand (8.560 point)
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!

Skrevet fre. d. 07. september 2012 kl. 03:45:41| #6

arne_v
arne_v (1.048.588 point)
I would probably let the thread write both messages to be consistent.

But that is style not function.

Skrevet fre. d. 07. september 2012 kl. 03:45:51| #7


Skriv et indlæg




Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] [img]link til billede[/img]
Web- og emailadresser omdannes automatisk til links

Log ind

   


Seneste spørgsmål

Bedste bog for en begynder?

Oprettet den 9. maj 2013 kl. 16.07
DBigShooter giver 30 point for svar | Giv et svar »

ArrayList

Oprettet den 5. maj 2013 kl. 17.38
frankedrengen giver 30 point for svar | Giv et svar »

Sæt actionlistener til jbutton (returneret fra en klasse)

Oprettet den 4. maj 2013 kl. 19.25
langkiller giver 30 point for svar | Giv et svar »








Tips & Tricks fra PC World

Teaser billede

Her er seks Google Labs-funktioner, som du skal slå til med det samme

Gmail Labs giver dig adgang til en masse smarte funktioner, som Googles ingeniører leger med i øjeblikket.


Anmeldelser fra PC World

Teaser billede

Test: Samsung Galaxy S4 er et hit - trods gøglertricks

Kan Samsung beholde førertrøjen i det store Android-race? Galaxy S4 er smækfyldt med innovative funktioner, men også med en del gøgl. Er det for meget? Få vores dom over Samsungs nye topmodel.


Seneste blogindlæg

Teaser billede

Tvangslukke spørgsmål: Hvad er den bedste løsning?

Hej Vi har mange åbne spørgsmål på Eksperten. Vi ville gerne tvangslukke dem - så et spørgsmål efter f.eks. 6 måneder lukkes. Men der er et par uklarheder som ville være gode at få lidt input til:...


Nyheder fra PC World

Teaser billede

Tre smarte trick som gør Windows 8 bedre

Boot direkte til skrivebordet, få en strategisk godt placeret luk-knap og slip for at logge ind. Her er tre tips til Windows 8, som gør det nemmere at blive venner med styresystemet.


Nyheder fra Computerworld

Teaser billede

Galleri: Her er Googles nyeste værktøj og legetøj

Google har i denne uge afholdt udviklerkonferencen I/O i San Francisco. Se her hvad søgegiganten kunne præsentere af nyskabelser.


IT Kurser
Samarbejdspartnere

Udgiver · © 2013 IDG Danmark A/S · Hørkær 18 · 2730 Herlev · Tlf.: 77 300 300 · Fax: 77 300 301 · Brug af personoplysninger