Avatar billede fredand Forsker
20. marts 2012 - 21:12 Der er 4 kommentarer og
1 løsning

How to use Swing and thread's?

Hello guys!

I hope for some hint's and idea's how develope this in a "best practice" maner.

My question is how to develop a swing app that in the background listens for changes in the file system.

Below I have a test app, but as you can see I have put the listener-code last in the main-method.

The app opens a new JFrame if there is any changes in the user.dir.

I bet there must be a better pattern for this. 

All ideas where to put the listener code are most welcome!

Best regards
Fredrik

package filelistener;

import java.io.File;

public class Listener extends JPanel
{
    private static JFrame jFrame = new JFrame("Listener");
    private static JLabel jLabel =  new JLabel( System.getProperty("user.dir" ));
    private static Path path = Paths.get( System.getProperty("user.dir" ));
    private static ListenerDialog listenerDialog;
   
    public Listener()
    {
        add(jLabel);
    }
   
    private static void createAndShowGUI()
    {       
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setResizable(false);
        jFrame.getContentPane().add(new Listener());
        jFrame.pack();
        jFrame.validate();
        jFrame.setVisible(true);   
    }
   
    public static void main(String[] args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
       
        try
        {
            WatchService watchService = path.getFileSystem().newWatchService();   
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); 
           
            for(;;)
            {
                WatchKey watckKey = watchService.take();         
                List<WatchEvent<?>> watchEvents = watckKey.pollEvents();         
                             
                for (WatchEvent watchEvent : watchEvents)
                {
                    if(listenerDialog == null)
                    {
                        listenerDialog = new ListenerDialog(jFrame);
                    }
                    listenerDialog.jTextArea.setText( listenerDialog.jTextArea.getText() +"\n"+ watchEvent.context().toString() );       
                }

                boolean valid = watckKey.reset();
                if (!valid)
                {
                    break;
                }           
            }
        }
        catch(Exception e)
        {           
            e.printStackTrace();
        }
    }
}

class ListenerDialog extends JFrame
{
    JPanel jPanel = new JPanel();
    JTextArea jTextArea = new JTextArea(20, 8);
   
    public ListenerDialog(JFrame parentFrame)
    {
        super("Dialog");
        jTextArea.setEditable(false);
        JScrollPane scrollPaneText = new JScrollPane(jTextArea,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        jPanel.add( scrollPaneText );
        getContentPane().add( jPanel );
        setResizable(false);
        pack();
        setVisible(true);
    }
}
Avatar billede arne_v Ekspert
20. marts 2012 - 21:25 #1
listenerDialog.jTextArea.setText

should be done on the event thread via EventQueue.invokeLater

your app is very different from how I write Swing apps, but I think the rest is OK
Avatar billede arne_v Ekspert
20. marts 2012 - 21:26 #2
An example from the shelf:


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class MovingBalls extends JFrame {
    public MovingBalls() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Moving balls");
        getContentPane().setLayout(new BorderLayout());
        Ball red = new Ball(200,200,50,Color.RED);
        Ball green = new Ball(400,200,50,Color.GREEN);
        Ball blue = new Ball(400,400,50,Color.BLUE);
        Ball yellow = new Ball(200,400,50,Color.YELLOW);
        MultiBalls mb = new MultiBalls(600, 600);
        mb.addBall(red);
        mb.addBall(green);
        mb.addBall(blue);
        mb.addBall(yellow);
        getContentPane().add(mb);
        (new BallMover(red, mb)).start();
        (new BallMover(green, mb)).start();
        (new BallMover(blue, mb)).start();
        (new BallMover(yellow, mb)).start();
        pack();
       
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new MovingBalls();
                f.setVisible(true);
            }
        });
    }
}
class MultiBalls extends JPanel {
    private List<Ball> balls;
    public MultiBalls(int w, int h) {
        setPreferredSize(new Dimension(w, h));
        balls = new ArrayList<Ball>();
    }
    public void addBall(Ball b) {
        balls.add(b);
    }
    @Override
    public void paint(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0,getWidth(), getHeight());
        for(Ball b : balls) {
            g.setColor(b.getC());
            g.fillOval(b.getX() - b.getR(), b.getY() - b.getR(), 2*b.getR(), 2*b.getR());
        }
    }
}
class Ball {
    private volatile int x;
    private volatile int y;
    private int r;
    private Color c;
    public Ball(int x, int y, int r, Color c) {
        this.x = x;
        this.y = y;
        this.r = r;
        this.c = c;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public int getR() {
        return r;
    }
    public void setR(int r) {
        this.r = r;
    }
    public Color getC() {
        return c;
    }
    public void setC(Color c) {
        this.c = c;
    }
}
class BallMover extends Thread {
    private Random rng = new Random(getId() + System.currentTimeMillis());
    private Ball b;
    private JPanel p;
    public BallMover(Ball b, JPanel p) {
        this.b = b;
        this.p = p;
    }
    @Override
    public void run() {
        for(;;) {
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int x = b.getX() + rng.nextInt(21) - 10;
            int y = b.getY() + rng.nextInt(21) - 10;
            x = Math.max(x, b.getR());
            x = Math.min(x, p.getWidth() - b.getR());
            y = Math.max(y, b.getR());
            y = Math.min(y, p.getHeight() - b.getR());
            b.setX(x);
            b.setY(y);
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    p.repaint();
                }
            });
        }
    }
}
Avatar billede fredand Forsker
21. marts 2012 - 19:52 #3
Hello Arne!

Thanks for a great example!

I put the file listener in a Thread and it works fine, and from that thread I do the GUI update like:

    public void run()
    {
        for (;;)
        {
            try
            {
                Thread.sleep(250);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
           
            eventString = watchFileSystem();
           
            if(eventString != null)
            {
                EventQueue.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        listenerDialog.jTextArea.setText( eventString );
                    }
                });
            }
        }
    }

It seems to work fine, but if you see something bad, feel free to say it!

Please give a svar so I can reward you mate!

Best regards
/Fredrik
Avatar billede arne_v Ekspert
22. marts 2012 - 00:46 #4
looks OK to me
Avatar billede arne_v Ekspert
22. marts 2012 - 00:46 #5
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