PDA

View Full Version : [Java] Chiusura forzata JFrame


divincodin
13-05-2009, 18:40
Ciao,non riesco a far chiudere un JFrame.Questo JFrame contiene un player con caricato un video,e vari bottoni...uno dei quali è il bottone "close" che dovrebbe fermare l'esecuzione del video e chiudere la finestra...ma non riesco.
Io ho fatto così

if (source==closeButton)
this.dispose();


Solo che non va...nel senso che il dispose funziona solo alla fine del video.In sostanza è come se quando il video è in esecuzione del player,il bottone diventasse inattivo e non cliccabile.
Se oltre al dispose() aggiungo il System.exit(0),il bottone "close" è come se fosse sempre inattivo però premendo la x della finestra si chiude tutta l'applicazione,compreso il frame principale.
Come posso risolvere?

banryu79
14-05-2009, 08:23
Ciao,non riesco a far chiudere un JFrame.Questo JFrame contiene un player con caricato un video,e vari bottoni...uno dei quali è il bottone "close" che dovrebbe fermare l'esecuzione del video e chiudere la finestra...ma non riesco.
Io ho fatto così

if (source==closeButton)
this.dispose();


Solo che non va...nel senso che il dispose funziona solo alla fine del video.In sostanza è come se quando il video è in esecuzione del player,il bottone diventasse inattivo e non cliccabile.
Se oltre al dispose() aggiungo il System.exit(0),il bottone "close" è come se fosse sempre inattivo però premendo la x della finestra si chiude tutta l'applicazione,compreso il frame principale.
Come posso risolvere?
Prova a postare un po' più di codice, anzi magari proprio tutta la classe che implementa il JFrame.
Sospetto che il problema abbia a che fare con la natura single threaded di Swing.

divincodin
14-05-2009, 09:56
Allora... nel file applicazione.java,all'interno dell'actionperformed ho inserito:

Object source=e.getSource();

if(source==apriVideo)
{
JFileChooser finestra_1 = new JFileChooser();
finestra_1.setDialogTitle("Apri video");
finestra_1.setAcceptAllFileFilterUsed(false);
finestra_1.setFileFilter(new aviFilter());
finestra_1.showOpenDialog(new JFrame());

//inserisco un try x l'eventuale eccezione che si può creare
//se nella JOptionPane al posto di selezionare il video
//premo il bottone "annulla"...infatti,così facendo,non darei nessun
//input "getAbsolutePath()" visto che non ho selezionato nessun video
try
{
File file = finestra_1.getSelectedFile();
pathfile=file.getAbsolutePath();
//richiamo il metodo "Grab()" della classe "VideoGrabbing"
VideoGrabbing.grab(pathfile);
}
catch(Exception e1){}
}



Quindi se seleziono dal menu "apriVideo" oltre il JFileChooser richiamo il metodo "Grab()" della classe "VideoGrabbing".

la classe VideoGrabbing è questa (premetto che è un pò incasinata...parte del codice l'ho trovato fatto...e quindi poi l'ho arricchito e adatato a ciò che mi serviva)


import java.io.*;
import java.beans.*;
import java.lang.Object;
import java.io.File;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.color.*;
import java.awt.image.ImageObserver;
import java.awt.image.BufferedImage;
import javax.media.*;
import javax.imageio.ImageIO;
import javax.media.format.VideoFormat;
import javax.media.control.FramePositioningControl;
import javax.media.protocol.DataSource;
import javax.media.control.FrameGrabbingControl;
import javax.media.util.*;
import javax.swing.JButton;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.imageio.*;
import javax.swing.border.*;
import javax.swing.filechooser.FileFilter;


public class VideoGrabbing extends JFrame implements ControllerListener,ActionListener
{
Player p;
FramePositioningControl fpc;
FrameGrabbingControl fgc;
Object waitSync = new Object();
boolean stateTransitionOK = true;
int totalFrames = FramePositioningControl.FRAME_UNKNOWN;
Image img;
int currentFrame;
Time currentTime;
static String urlVideo,urlFrames;
static String duraVideo,nFramesVideo;
static JComboBox cbox;
String ValoriCamp[]={"1","2","3","4","5"};
int camp=Integer.parseInt((String)ValoriCamp[0]);

JPanel controlPanel;
JPanel infoPanel;
JButton grabButton;
JButton closeButton;
JPanel AlertVideo;
JButton Ok;
String pathCommentsTxt;

// Creazione del Player che verrà utilizzato per il grabbing.
public boolean open(DataSource ds)
{
System.err.println("Creato player per video in formato " +ds.getContentType());

try
{
//inizializzo il player che si trova nello stato Unrealized
p=Manager.createPlayer(ds);
}
catch (Exception e)
{
System.err.println("Creazione del player per il DataSource: "+ e + " fallita!");
return false;
}

p.addControllerListener(this);

p.realize();

if (!waitForState(p.Realized))
{
System.err.println("Realizzazione del player fallita!");
return true;
}

// Provo a ottenere FramePositioningControl dal player.
fpc = (FramePositioningControl)p.getControl("javax.media.control.FramePositioningControl");
// Provo a ottenere FrameGrabbingControl dal player.
fgc = (FrameGrabbingControl)p.getControl("javax.media.control.FrameGrabbingControl");

if (fpc == null)
{
System.err.println("Il player non supporta il " +"FramePositioningControl.");
return false;
}

Time duration = p.getDuration();

if (duration != Duration.DURATION_UNKNOWN)
{

//System.err.println("Durata del video: " +duration.getSeconds() + " secondi");
duraVideo=new String(duration.getSeconds() + " secondi");

totalFrames = fpc.mapTimeToFrame(duration);

if (totalFrames != FramePositioningControl.FRAME_UNKNOWN)
{
//System.err.println("Numero totale di frames del video: "+ totalFrames);
nFramesVideo=new String(""+totalFrames);
}
else
System.err.println("Il FramePositiongControl non " +" supporta mapTimeToFrame.");
}

else
{ System.err.println("Durata del video sconosciuta!"); }

// Prefetch del player.
p.prefetch();
if (!waitForState(p.Prefetched))
{
System.err.println("Prefetch del player fallito.");
return false;
}
//setDefaultCloseOperation(EXIT_ON_CLOSE);

// Costruzione dell'interfaccia grafica.
setLayout(new BorderLayout());
controlPanel=new JPanel();
infoPanel=new JPanel();

grabButton = new JButton("Grab");
closeButton = new JButton("Close");
grabButton.addActionListener(this);
closeButton.addActionListener(this);
controlPanel.add(new JLabel(urlVideo.substring(5,urlVideo.length())));
cbox=new JComboBox(ValoriCamp);
cbox.addActionListener(this);
controlPanel.add(cbox);
controlPanel.add(grabButton);
controlPanel.add(closeButton);

infoPanel.add(new JLabel("Durata del video: "+duraVideo));
infoPanel.add(new JLabel(" Numero totale di frames del video: "+nFramesVideo));


Component vc;
if ((vc = p.getVisualComponent()) != null)
{
add("Center",vc);
}
add("South", controlPanel);
add("North",infoPanel);
setTitle("VideoGrabber");
setLocation(385,250);
setVisible(true);
return true;
}


public void addNotify()
{
super.addNotify();
pack();
}

//Aspetta finché il player non è transitato in un dato stato.
//Return false se la transizione è fallita.

boolean waitForState(int state)
{
synchronized (waitSync)
{
try
{
while (p.getState() < state && stateTransitionOK)
waitSync.wait();
}
catch (Exception e) {}
}
return stateTransitionOK;
}



public void actionPerformed(ActionEvent ae)
{

String command = ae.getActionCommand();
Object source=ae.getSource();
int k=1;
int j=00;

// ****** Salvataggio Cartelle che conterranno file Jpg ******
if (source==grabButton)
{
JFileChooser finestra= new JFileChooser();
finestra.setDialogTitle("Salva Files");
finestra.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
finestra.setCurrentDirectory( new File ("c:\\"));


int risposta=finestra.showSaveDialog(this);
if (risposta == JFileChooser.APPROVE_OPTION)
{

try
{
File cart = finestra.getSelectedFile();
urlFrames=cart.getAbsolutePath();
int frameId=0;
for ( int i=0; i<=totalFrames; i=i+camp)
{
j++;
frameId++;
// inizialmente mi posiziono sul frame 0 (istante 0)
if (i==0)
fpc.skip(0);
// poi mi posiziono sui frame successivi, secondo il campionamento
else
fpc.skip(camp);

// grabba il frame relativo
if (currentFrame !=FramePositioningControl.FRAME_UNKNOWN)
{
currentFrame =fpc.mapTimeToFrame(p.getMediaTime());
currentTime = fpc.mapFrameToTime(i);
}

Buffer buff = new Buffer();
buff = fgc.grabFrame();
// converte buffer - image
BufferToImage bti = new BufferToImage((VideoFormat)buff.getFormat());
img = bti.createImage(buff);

if(j%65==0) k++; //k è il nome della cartella
//creo cartelle e file dei commenti
new File(urlFrames+"/"+k).mkdirs();
String pathFrame = (urlFrames+"/"+k+"/"+j+".jpg");
File fileFrame = new File(pathFrame);
pathCommentsTxt=(urlFrames+"/"+k+"/Comments_"+k+".txt");
FileOutputStream file = new FileOutputStream(pathCommentsTxt);

//inserisco 64 spazi vuoti all'interno di ogni file .txt creato
//altrimenti si generano eccezioni
File f1=new File(pathCommentsTxt);
FileOutputStream fos1=new FileOutputStream(f1);
PrintStream ps1=new PrintStream(fos1);
for (int l=0;l<65;l++)
ps1.println("");


try
{
System.err.println("Sto salvando il frame n." +currentFrame + " del video " +" Tempo: " +currentTime.getSeconds());
ImageSaver(img,fileFrame);
}
catch (Exception e)
{
System.err.println("Non riesco a salvare il " +"frame, forse non esiste " +"la cartella " + e);
}
}
System.err.println("Numero di frames salvati:" + frameId);
}

catch (Exception EX)
{
System.out.println("errore");
}
}
}

if (source==closeButton)
{
this.dispose();
//System.exit(0);
}

else if (source==cbox)
{
//recupero la stringa selezionata dalla JComboBox
//e faccio il casting ad Int per ricavare il campionamento selezionato
//il 1° camp sarebbe il valore di defaul (0) qualora l'utente non clicca
// sulla JComboBox se magari vuole che il camp sia 1(già come 1° elemento
//della lista e che quindi potrebbe sembrare selezionato...ma nn lo è).
//camp=Integer.parseInt((String)ValoriCamp[0]);
camp=Integer.parseInt((String)cbox.getSelectedItem());
}

}


//Controller Listener.

public void controllerUpdate(ControllerEvent evt)
{
if (evt instanceof ConfigureCompleteEvent || evt instanceof RealizeCompleteEvent || evt instanceof PrefetchCompleteEvent)
{
synchronized (waitSync)
{
stateTransitionOK = true;
waitSync.notifyAll();
}
}
else if (evt instanceof ResourceUnavailableEvent)
{
synchronized (waitSync)
{
stateTransitionOK = false;
waitSync.notifyAll();
}
}
else if (evt instanceof EndOfMediaEvent)
{
p.setMediaTime(new Time(0));
}
else if (evt instanceof SizeChangeEvent) {}
}


void this_windowClosing(WindowEvent e)
{
this.dispose();
}


public void ImageSaver (Image img,File fileFrame) throws IOException
{


//Codifica un BufferedImage in formato Jpeg format e lo salva su
// file
// @param img è l'immagine da salvare
// @param fileFrame è un File che decrive dove si vuole salvare
// l'immagine
// @throws java.io.IOException se l'immagine non può essere
// codificata
// e/o salvata


BufferedImage bi=null;
try
{
if (!(img instanceof BufferedImage))
{
ImageObserver io=new ImageObserver() { public boolean imageUpdate(Image im, int info,int x, int y, int w, int h) {return false;}};
bi = new BufferedImage(img.getWidth(io),img.getHeight(io),BufferedImage.TYPE_INT_RGB);
bi.getGraphics().drawImage(img,0,0,io);
img=bi;
}
else
bi=(BufferedImage)img;

ImageIO.write(bi, "JPG", fileFrame);
}
catch (Exception e)
{
throw new IOException("Salvataggio dell'immagine fallito: " +e);
}
}


public static void grab(String pathfile)
{
urlVideo="file:"+pathfile;
//camp=1;
MediaLocator ml;
if ((ml = new MediaLocator(urlVideo)) == null)
System.err.println("Impossibile costruire MediaLocator "+ "dalla url: " + pathfile);

DataSource ds = null;

// Crea un DataSource da un dato MediaLocator
try
{
ds=Manager.createDataSource(ml);
}
catch (Exception e)
{
System.err.println("Impossibile creare Datasource da: "+ ml);
System.err.println("Eccezione: "+e);
System.exit(0);
}
VideoGrabbing VideoGrabbing = new VideoGrabbing();
if (!VideoGrabbing.open(ds))
System.exit(0);
}
}


Se ti può esser d'aiuto posso postarti anche l'intera classe applicazione.
Cmq ti ringrazio già da adesso x il tempo che stai impiegando x aiutarmi.

banryu79
14-05-2009, 12:44
* edit

divincodin
14-05-2009, 13:51
Non ho ben capito se era un si...cmq la posto ugualmente :D


import java.io.*;
import java.awt.*;
import java.io.File;
import java.beans.*;
import java.lang.Object;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.border.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.JButton;
import javax.swing.*;
import javax.imageio.*;
import javax.imageio.ImageIO;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.color.*;
import java.awt.image.ImageObserver;
import java.awt.image.BufferedImage;
import java.util.*;


public class Applicazione
{
public static void main(String [] args)
{
Frame frame=new Frame();
frame.show();
}
}



class Frame extends JFrame implements ActionListener,ListSelectionListener
{
pannelloa a=new pannelloa();
JMenuItem apriCartella,apriVideo;
File f;
String pathfile;
JList ListaIcone;
JPanel PannelloAnte,PannelloComme,ModificaSalva;
JLabel Label_1;
JTextArea TextArea;
String FileDiTestodir;
ArrayList righe; //conterrà le righe del file txt corrente
JButton modifica,salva;
String corrente;
int indexcorrente;

public Frame()
{
setTitle("Analizzatore Video Medicali");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setExtendedState(MAXIMIZED_BOTH);

JMenuBar barra=new JMenuBar();
JMenu menu=new JMenu("File");
apriVideo=new JMenuItem("Apri Video");
apriCartella=new JMenuItem("Apri Cartella Immagini");
barra.add(menu);
menu.add(apriVideo);
menu.add(apriCartella);
apriVideo.addActionListener(this);
apriCartella.addActionListener(this);
this.setJMenuBar(barra);

ListaIcone=new JList();
//ListaIcone.setPreferredSize(new Dimension (10,200));
ListaIcone.setCellRenderer(new ImageViewerCellRenderer());
ListaIcone.addListSelectionListener(this);

PannelloAnte=new JPanel();
PannelloAnte.setLayout(new BorderLayout());

Label_1=new JLabel();
Label_1.setPreferredSize(new Dimension (205,650));
Label_1.setHorizontalAlignment(SwingConstants.CENTER);

PannelloComme=new JPanel();
PannelloComme.setLayout(new FlowLayout(FlowLayout.CENTER,4,4));

TextArea=new JTextArea();
TextArea.setEditable(false);
TextArea.setLineWrap(true);
Font font=new Font("Times New Roman",Font.BOLD,14);
TextArea.setFont(font);
JScrollPane TextAreaScrollPane=new JScrollPane(TextArea,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
TextAreaScrollPane.setPreferredSize(new Dimension(880,50));

ModificaSalva=new JPanel();
ModificaSalva.setLayout(new BorderLayout());
modifica=new JButton("Modifica");
modifica.addActionListener(this);
modifica.setEnabled(false);
salva=new JButton("Salva");
salva.addActionListener(this);
salva.setEnabled(false);
ModificaSalva.add(modifica,BorderLayout.NORTH);
ModificaSalva.add(salva,BorderLayout.SOUTH);

JScrollPane listScrollPane=new JScrollPane (ListaIcone,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
listScrollPane.setPreferredSize(new Dimension(150,600));

PannelloAnte.add("North",Label_1);
PannelloAnte.add("Center",PannelloComme);

PannelloComme.add(TextAreaScrollPane);
PannelloComme.add(ModificaSalva);

a.add(listScrollPane,BorderLayout.WEST);
a.add(PannelloAnte,BorderLayout.CENTER);


Container pane=getContentPane();
pane.add(a);
}

public void actionPerformed(ActionEvent e)
{
Object source=e.getSource();

if(source==apriVideo)
{
JFileChooser finestra_1 = new JFileChooser();
finestra_1.setDialogTitle("Apri video");
finestra_1.setAcceptAllFileFilterUsed(false);
finestra_1.setFileFilter(new aviFilter());
finestra_1.showOpenDialog(new JFrame());

//inserisco un try x l'eventuale eccezione che si può creare
//se nella JOptionPane al posto di selezionare il video
//premo il bottone "annulla"...infatti,così facendo,non darei nessun
//input "getAbsolutePath()" visto che non ho selezionato nessun video
try
{
File file = finestra_1.getSelectedFile();
pathfile=file.getAbsolutePath();
//richiamo il metodo "Grab()" della classe "VideoGrabbing"
VideoGrabbing.grab(pathfile);
//System.exit(0);
}
catch(Exception e1)
{
//System.err.println (e1);
}
}

if(source==apriCartella)
{
try
{
//aggiornaTxt(righe);
File f=new File(FileDiTestodir);
FileOutputStream fos=new FileOutputStream(f);
PrintStream ps=new PrintStream(fos);
for (int l=0;l<righe.size();l++)
ps.println(righe.get(l));
}

catch(Exception e2){}

JFileChooser finestra_2=new JFileChooser();
finestra_2.setDialogTitle("Apri cartella immagini");
finestra_2.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if(finestra_2.showOpenDialog(a)==JFileChooser.APPROVE_OPTION)
//richiamo il metodo azione passando la cartella selezionata
azione(finestra_2.getSelectedFile());
}

if(source==modifica)
{
salva.setEnabled(true);
TextArea.setEditable(true);
}

if(source==salva)
{
System.out.println(TextArea.getText());
System.out.println(indexcorrente);
//così lo aggiungeva,invece io devo sostituirlo...
//righe.add(indexcorrente,TextArea.getText());
//ecco xkè adesso uso set
righe.set(indexcorrente,TextArea.getText());

System.out.println(righe);
//una volta salvato il contenuto della JTextArea,riporto
//il bottone "salva" inattivo
salva.setEnabled(false);
}
}



public void azione(File dir)
{
try
{
//array di file
File f[]=dir.listFiles(new ImageFilenameFilter ());
//ordinamento numerico delle immagini nella cartella corrente
//istanziazione di classe anonima
Comparator comp=new Comparator() {
public int compare(Object filea, Object fileb)
{
File a=(File)filea;
File b=(File)fileb;
String nameA=a.getName();
String nameB=b.getName();
nameA=nameA.substring(0,nameA.indexOf("."));
nameB=nameB.substring(0,nameB.indexOf("."));
int indexA = Integer.parseInt(nameA);
int indexB = Integer.parseInt(nameB);
return indexA == indexB ? 0 : indexA > indexB ? 1 : -1;
}
};
Arrays.sort(f,comp);

//array di oggetti ImageViewerItem delle dimensioni dell'array precedente
ImageViewerItem [] items = new ImageViewerItem[f.length];
for(int i=0;i<f.length;i++)
{
items[i]=new ImageViewerItem(f[i],-1,100);
}
//Costruisce una ListModel da un array di oggetti e dopo applica il setModel ad essa
ListaIcone.setListData(items);

//prendo il file txt nella cartella corrente
File ArrayTxt[]=dir.listFiles(new TxtFilenameFilter ());
for(int j=0;j<ArrayTxt.length;j++)
{
FileDiTestodir=ArrayTxt[j].getAbsolutePath();
}

//RandomAccessFile raf = new RandomAccessFile(FileDiTestodir,"rw");
BufferedReader input=new BufferedReader(new FileReader(new File(FileDiTestodir)));
String linea=input.readLine();
righe=new ArrayList();
//riempio l' ArrayList
while(linea!=null)
{
righe.add(linea); // aggiunge una linea letta alla lista di String
linea=input.readLine();
}
modifica.setEnabled(true);
}

catch (Exception e)
{
System.err.println (e);
}
//una volta caricato il contenuto della cartella abilito il bottone "modifica"
//FARE IN MODO CHE IL BOTTONE "MODIFICA" DIVENTI ATTIVO DOPO CHE CLICCO SU UNA FOTO
modifica.setEnabled(true);

}


public void valueChanged (ListSelectionEvent ex)
{
ImageViewerItem item = (ImageViewerItem) ListaIcone.getSelectedValue();
if(item != null)
{
try
{
ImageIcon imageIcon = item.loadFullImage();
Label_1.setIcon(imageIcon);
//gestire eccezione (eccezione che si crea quando le righe nel txt sn meno di 64
indexcorrente=ListaIcone.getSelectedIndex();
corrente=(String)righe.get(indexcorrente);
TextArea.setText(corrente);
//System.out.println(indexcorrente);
}
catch (Exception exc)
{
exc.printStackTrace();
JOptionPane.showMessageDialog (this, "Error loading image", "ERROR", JOptionPane.ERROR_MESSAGE);
}
}
}

}


class pannelloa extends JPanel
{
public pannelloa()
{
setLayout (new BorderLayout ());
}
}


class aviFilter extends FileFilter
{
public boolean accept(File f)
{
String nome = f.getName().toLowerCase();
if (nome.endsWith("avi")||f.isDirectory())
return true;
else
return false;
}

public String getDescription ()
{
return "File (*.avi)";
}
}


class ImageFilenameFilter implements FilenameFilter
{
public boolean accept(File dir, String name)
{
String nameLower=name.toLowerCase ();

return (nameLower.endsWith(".jpg") ||
nameLower.endsWith(".jpeg"));
}
}


class TxtFilenameFilter implements FilenameFilter
{
public boolean accept(File dir,String name)
{
String nameLower=name.toLowerCase();

return (nameLower.endsWith(".txt"));
}
}

banryu79
14-05-2009, 13:52
Facciamo una piccola considerazione.

Devi sapere che in pratica l'architettura di AWT/Swing è "single threaded".
Ciò significa che un solo thread si occupa di tutto il lavoro, ovvero smazzarsi tutti gli eventi Swing/AWT, uno per uno, che preleva dalla AWT Event Queue.

Questo thread si chiama AWT Event Dispatching Thread.

Il corpo di un metodo actionPerformed() di un ActionListener viene eseguito proprio dall'EDT.
Essendo l'EDT impegnato ad eseguire il codice che tu scrivi nel corpo del metodo actionPerformed per implementare il tuo ActionListener, per esempio quando includi la chiamata al metodo grab() della tua classe (che internamente a sua volta chiama open(): metodo che fa un bel po' di roba) tieni "inchiodato" l'EDT a eseguire tutto quel codice, così lui può ricominciare a rispondere agli eventi AWT/Swing (tipo, aggiornare i componenti grafici) solo dopo che ha finito di lavorare per te.

La soluzione per ovviare è incapsulare il codice da eseguire dentro un Runnable/Thread che verrà mandato in esecuzione in modo asincrono: in questo modo l'EDT sarà di nuovo libero di rispondere agli eventi Swing.

In pratica ti crei un nuovo thread che incapsula il tuo codice da eseguire in modo asincrono, per esempio:

// dentro actionPerformed()
//...
if(source==apriVideo)
{
final JFileChooser finestra_1 = new JFileChooser();
finestra_1.setDialogTitle("Apri video");
finestra_1.setAcceptAllFileFilterUsed(false);
finestra_1.setFileFilter(new aviFilter());
finestra_1.showOpenDialog(new JFrame());

Thread grabvideo = new Thread()
{
public void run()
{
try
{
File file = finestra_1.getSelectedFile();
pathfile=file.getAbsolutePath();
VideoGrabbing.grab(pathfile);
}
catch(Exception e1){}
}
};
grabvideo.start();
}

Devi anche dichiarare come final il JFileChooser dato che referenziamo questo oggetto dentro la classe innestata anonima (l'implementazione del Thread).


Può poi capitare di avere a che fare con l'altra faccia della medaglia: trovarsi in un thread che non è l'EDT e dover mandare in esecuzione del codice che aggiorna/mostra/nasconde componenti AWT/Swing.
Anche in questo caso sarà neccessario incapsulare il codice dentro un Runnable, ma con lo scopo di "appendere" questo codice alla AWT Event Queue: questo per fare in modo che sia l?EDT ad eseguire quel codice.
In questo caso il Runnable viene passato come parametro al metodo invokeLater della classe javax.swing.SwingUtilities.
Chiamare invokeLater, come suggerito dal nome stesso del metodo, significa dire che il codice contenuto nel Runnable va "appeso" alla coda degli eventi e verrà quindi eseguito non appena l'EDT avrà consumato tutti gli eventi presenti nell'AWT Event Queue.

Un esempio di questo è quando si realizza la visualizzazione a video di un Frame:

public static main(String[] args)
{
final JFrame frame = new JFrame("Main Window");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// ... imposta alcune proprietà del frame

// accodo la realizzazione/visualizzazione del frame nella AWT Event Queue
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
frame.pack();
frame.setVisible(true);
}
});
}


A questo punto, dopo aver letto velocemente gli spezzoni di codice postato, ti consiglio di rivedere e riprogettare con calma, alla luce delle considerazioni fatte sul funzionamento a single thread di AWT/Swing, le tue classi e i rispettivi listener associati (ovvero le implementazioni dei vari metodi 'actionPerformed').

Devi separare bene i lavori(task/blocchi di codice) da eseguire nell'EDT da quelli che invece vanno eseguiti fuori, in altri thread; inoltre devi sapere sempre se un certo pezzo di codice si trova nel contesto di esecuzione dell''EDT (in pratica appena si "entra" nel corpo di un actionPerformed di un Listener il cotesto di esecuzione è quello dell'EDT) o da un'altro thread.

banryu79
14-05-2009, 14:05
Altri post nel Forum che hanno, direttamente o indirettamente a che fare con l'EDT:
http://www.hwupgrade.it/forum/search.php?searchid=9275578

banryu79
14-05-2009, 14:19
Per maggior precisione, ecco la cosidetta "Single-thread rule":

The single-thread rule

Here's the rule:

Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.

This rule might sound scary, but for many simple programs, you don't have to worry about threads. Before we go into detail about how to write Swing code, let's define two terms: realized and event-dispatching thread.

Realized means that the component's paint() method has been or might be called. A Swing component that's a top-level window is realized by having one of these methods invoked on it: setVisible(true), show(), or (this might surprise you) pack(). Once a window is realized, all components that it contains are realized. Another way to realize a component is to add it to a container that's already realized. You'll see examples of realizing components later.

The event-dispatching thread is the thread that executes drawing and event-handling code. For example, the paint() and actionPerformed() methods are automatically executed in the event-dispatching thread. Another way to execute code in the event-dispatching thread is to use the SwingUtilities invokeLater() method.

Presa da questa pagina (http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#exceptions), se vuoi investigare ulteriormente.

divincodin
14-05-2009, 15:20
Ho provato ad inserire la parte di codice che hai modificato ma purtroppo non cambia nulla.
C'è da dire che per questa parte di java (elaborazioni di immagini e quant'altro) sn bianco totale.Avendo trovato il codice di un programma che faceva il Grab di un video,speravo di poterlo estendere creando anche una discreta interfaccia grafica.Ci sono riuscito ma in parte... :)
Leggendo ho capito parecchio di ciò che hai scritto...ma nonostante tu sia stato molto preciso nel darmi qualsiasi tipo di delucidazione,mi sa che devo approfondire un pò tutto l'argomento.

banryu79
14-05-2009, 17:06
Ho provato ad inserire la parte di codice che hai modificato ma purtroppo non cambia nulla.

Quella era solo una modifica, usata a titolo di esempio: da sola non ti risolve la situazione; devi mettere mano a tutto il codice di quella classe.


Leggendo ho capito parecchio di ciò che hai scritto...ma nonostante tu sia stato molto preciso nel darmi qualsiasi tipo di delucidazione,mi sa che devo approfondire un pò tutto l'argomento.

Una volta che hai capito come identificare e separare il codice che deve essere eseguito nell'EDT dal codice che puoi eseguire in altri thread "normali" sei a cavallo.

Una cosa: quando si scatena l'azione sul bottone "Close" del Player video dovrebbero succedere due cose:
- il video in riproduzione si ferma;
- il frame che contiene il player viene chiuso.

Se cliccando sul bottone "Close" mentre il video è in esecuzione il bottone sembra non rispondere perchè la grafica del bottone non viene aggiornata, e il comando di chiusura della finestra non viene eseguito, bisognerebbe verificare che il codice che esegue la riproduzione del video non sia stato fatto eseguire dall'EDT: se fosse questo il caso, allora va da se, per i motivi che abbiamo preso in considerazione prima, che l'EDT è impegnato fino a che l'esecuzione del video non termina.
Non escludo che il motivo potrebbe anche risiedere altrove (non mi sono preso la briga di esaminare tutto il codice della classe postata) ma prima sarebbe opportuno corregere il sorgente rispettando la natura single threaded di AWT/Swing.

divincodin
18-05-2009, 22:54
Ho letto un pò di slides riguardo il multithreading in java e parecchie discussioni su vari forum.Ho capito il motivo x il quale dovrei creare un nuovo thread,però non sono ugualmente in grado di metterlo in atto.
E' da 3 giorni che faccio prove,modifiche...ma il risultato sperato ancora non l'ho raggiunto! :confused:
Ho apportato alcune modifiche...non nell'actionperformed del file "applicazione.java" (come avevi scritto tu),ma all'interno dell'actionperformed del file "VideoGrabbing.java".
All'inizio della classe VideoGrabbing,oltre alle tante variabili ho dichiarato anche "Thread grabvideo;" che poi userò dentro l'actionperformed....che ti riporto qui di seguito:


public void actionPerformed(ActionEvent ae)
{
Object source=ae.getSource();

// ****** Salvataggio Cartelle che conterranno file Jpg ******
if (source==grabButton)
{
final JFileChooser finestra= new JFileChooser();
finestra.setDialogTitle("Salva Files");
finestra.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
finestra.setCurrentDirectory( new File ("c:\\"));


int risposta=finestra.showSaveDialog(this);
if (risposta == JFileChooser.APPROVE_OPTION)
{
grabvideo = new Thread()
{
public void run()
{
....
....
....
}
};
grabvideo.start();
}
}


if (source==closeButton)
{
grabvideo.interrupt();
}


Così facendo,nel menu del frame iniziale (classe Applicazione.java) "apri cartella immagini" non funziona...invece "apri video" funziona e,durante il grab,se premo il bottone "Close" alla 3a volta che lo premo si ferma il video.Se poi premo la x della finestra col player,si chiude.Quindi almeno adesso penso di aver diviso il thread proprio perchè adesso i bottoni del player sn attivi.
Diciamo che su per giù si è sistemata una cosa e se n'è disfatta un'altra! :D