Ciao!


Sono da poco tornato sull'argomento thread, e dopo aver letto un po' di tutorial e qualcosa sui forum ho voluto provare a creare una stupida applicazione che faccia un qualche lavoretto in background.
In particolare conto il numero di file e di cartelle presenti in una directory a scelta.
Ora, visto che la ricerca può durare anche molto, ho voluto creare un frame con una progress bar (in questo caso in modalità indeterminata ma in altre applicazioni che ho in mente sarebbe più utile).
Dallo stesso frame voglio avere la possibilità di interrompere la ricerca, chiudendo la finestrella o premendo un pulsante.


Ho realizzato il metodo di background utilizzando la classe SwingWorker, ma non so se potrei migliorare la connessione che ho creato tra lo SwingWorker e il frame contenente la progressbar:


- Innanzitutto chiamo il metodo execute() sullo SwingWorker all'interno del costruttore di quello che ho chiamato "WaitingFrame", ma la cosa non mi piace molto...
- Il dispose() del WaitingFrame l'ho inserito nel metodo done() dello SwingWorker, ma sono assolutamente sicuro che non possa verificarsi il caso in cui una ricerca veloce termini prima che il frame sia stato effettivamente reso visibile?
( Non vorrei cioè che il frame di caricamento rimanga visibile per errore in qualche caso)
- Può andare bene l'uso un po' grezzo delle variabili booleane all'interno dello SwingWorker, e la semplice interruzione di quest'ultimo con l'utilizzo del metodo cancel(true)?


Posto qua il codice completo, ogni suggerimento è ben accetto


codice:
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import javax.swing.*;
import javax.swing.border.*;
public class CountFiles
{
	public static void main(String[] args)throws Exception
	{
		SwingUtilities.invokeLater(new Runnable(){
			public void run(){
				try
				{
					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					new CountFilesFrame().setVisible(true);
				}
				catch(Exception ex){
					ex.printStackTrace();
				}
			}
		});
	}
}
class CountFilesFrame extends JFrame
{
	private JTextField field;
	public CountFilesFrame()
	{
		super("Conta File e Cartelle");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setResizable(false);
		JPanel pane=(JPanel)getContentPane();
		pane.setBackground(Color.WHITE);
		pane.setBorder(new EmptyBorder(5,20,5,20));
		JPanel center=new StyledPanel(pane,BorderLayout.CENTER,new FlowLayout(FlowLayout.LEFT,5,10)),bottom=new StyledPanel(pane,BorderLayout.SOUTH,new FlowLayout(FlowLayout.LEFT,20,0));
		// Center panel
		center.add(new JLabel("Cartella :"));
		String text="";
		try{
			File folder=new File("../");
			text=folder.exists()?folder.getCanonicalPath():"";
		}
		catch(Exception ex){}
		field=new JTextField(text,25);
		center.add(field);
		// JTextArea
		String newLine=System.getProperty("line.separator"),message="Scegliere la cartella da cui far partire la ricerca."+newLine+
		"Sara' contato il numero di file e di cartelle presenti "+newLine+"nella directory inserita e in tutte le sottocartelle";
		JTextArea area=new JTextArea(message);
		area.setEditable(false);
		area.setFont(field.getFont());
		pane.add(area,BorderLayout.NORTH);
		// Bottom panel
		bottom.add(new JButton(new AbstractAction("Cambia Cartella"){
			public void actionPerformed(ActionEvent e){
				changeDirectory();
			}
		}));
		bottom.add(new JButton(new AbstractAction("Inizia ricerca"){
			public void actionPerformed(ActionEvent e){
				new WaitingFrame(CountFilesFrame.this);
			}
		}));
		pack();
		setLocationRelativeTo(null);
	}
	public void changeDirectory()
	{
		JFileChooser chooser=new JFileChooser(field.getText());
		chooser.setDialogTitle("Cambia Cartella");
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		if(chooser.showDialog(this,"Scegli")==JFileChooser.APPROVE_OPTION)
		{
			try
			{
				File selected=chooser.getSelectedFile();
				if(selected.exists())field.setText(selected.getCanonicalPath());
			}
			catch(Exception ex){}
		}
	}
	private class WaitingFrame extends JFrame
	{
		private Counter counter;
		public WaitingFrame(CountFilesFrame f)
		{
			super("Ricerca File");
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
			addWindowListener(new WindowAdapter(){
				public void windowClosing(WindowEvent e){
					stopCounter();
				}
			});
			setResizable(false);
			JPanel pane=(JPanel)getContentPane(),buttonPanel=new StyledPanel(pane,BorderLayout.SOUTH,new FlowLayout(FlowLayout.CENTER,0,10));
			JLabel label=new JLabel("Conteggio in corso...",JLabel.CENTER);
			label.setBorder(new EmptyBorder(0,0,10,0));
			pane.add(label,BorderLayout.NORTH);
			pane.setBackground(Color.WHITE);
			pane.setBorder(new EmptyBorder(10,40,0,40));
			JProgressBar progressBar=new JProgressBar(0,100);
			progressBar.setBorderPainted(false);
			progressBar.setIndeterminate(true);
			pane.add(progressBar,BorderLayout.CENTER);
			buttonPanel.add(new JButton(new AbstractAction("Annulla"){
				public void actionPerformed(ActionEvent e){
					stopCounter();
				}		
			}));
			while(pane.getSize().width!=pane.getPreferredSize().width)pack();
			setLocationRelativeTo(null);
			setVisible(true);
			(counter=new Counter()).execute();
		}
		public void stopCounter()
		{
			counter.interrupt();
			counter.cancel(true);
		}
		private class Counter extends SwingWorker<Void,Void>
		{
			private boolean valid=true,interrupted=false;
			private int filesNumber=0,foldersNumber=0;
			protected Void doInBackground()
			{
				File folder=new File(field.getText());
				if(!folder.exists()||!folder.isDirectory())valid=false;
				else countFiles(folder);
				return null;
			}
			protected void done()
			{
				dispose();
				if(interrupted)return;
				else if(!valid)JOptionPane.showMessageDialog(CountFilesFrame.this,"Inserire una cartella valida","Percorso specificato errato",JOptionPane.ERROR_MESSAGE);
				else JOptionPane.showMessageDialog(CountFilesFrame.this,"Sono stati trovati "+(foldersNumber-1)+" cartelle e "+filesNumber+" file","Ricerca completata",JOptionPane.INFORMATION_MESSAGE);
			}
			private void countFiles(File file)
			{
				if(file.isDirectory())
				{
					foldersNumber++;
					for(File nested:file.listFiles())countFiles(nested);			
				}
				else filesNumber++;
			}
			public void interrupt()
			{
				interrupted=true;
			}
		}
	}
}
class StyledPanel extends JPanel
{
	public StyledPanel(JPanel parent,String position,LayoutManager layout)
	{
		super(layout);
		setBackground(Color.WHITE);
		parent.add(this,position);
	}
}