Newsgroup: it.comp.java
Titolo: impossibile trovare o caricare la classe principale MENU

Come da oggetto ed il tutto non RUN più
 
Sto usando Netbeans e funzionava tutto, ho lavorato per un'oretta su un 
form diverso da quello di avvio che si chiama MENU, lancio e ...patratac!
 
Dove devo metter mano?
 
-- 
Gulp®
(forse mi sono perso qualcosa :))

Il 04/04/15 22:22, Gulp® ha scritto:
 
No, per la verità un cambiamento in MENU l'ho fatto, ma con mio 
sconcerto si tratta solo di questo
 
    private void btnNewCliActionPerformed(java.awt.event.ActionEvent 
evt) {
         // TODO add your handling code here:
         this.setVisible(false);
         new NuovoCliente().setVisible(true);
     }
Codice posizionato, si badi bene, normalmente tra gli altri Button 
ActionPerformed.
Se elimino quelle righe di codice, MENU riparte.
 
Basito.
Di cosa si può trattare?


 Se elimino quelle righe di codice, MENU riparte.
Questa tua domanda evidenzia una quantita' di cose che dovresti sapere 
ma che non sai. Spero che tu non ti offenda se mi dilungo nella 
spiegazione: e' pasqua, c'e' brutto tempo, a messa non ci vado, ho gia' 
messo su l'arrosto quindi ho tempo per dilungarmi!
 
Se implementi l'interfaccia ActionListener, e' obbligatorio che il 
metodo sia quello dichiarato nell'interfaccia ActionListener, ovvero:
public void actionPerformed(ActionEvent evt)
 
Ovviamente non so dove sia collocato il tuo metodo e di cosa sia parte, 
ho solo ipotizzato.
 
Se intendevi isolare l'handler di un bottone in particolare, avresti 
forse potuto creare una un ActionListener privato di quel bottone, ad 
esempio:
 
button.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent evt) {
     setVisible(false);
     new NuovoCliente().setVisible(true);
   }
});
Nota che ho tolto "this", perche' in questo caso avrebbe indicato 
l'istanza del listener stesso, mentre setVisible continua a riferirsi al 
metodo della classe in cui e' incluso il codice. In generale, invece di 
this potresti utilizzare MiaClasse.this, stante che MaiClasse sia il 
nome della classe outer, eventualmente per differenziare un metodo con 
lo stesso nome, se ce ne fosse bisogno, comunque utile per esplicitare 
di chi sia il metodo da invocare, anche al solo fine di leggibilità.
Ad esempio (ovviamente e' inutile istanziare un nuovo ActionListener se 
poi devi chiamare quello generale della classe):
 
public MiaClasse extends JPanel implements ActionListener {
   JToolBar toolBar;
...
   public void actionPerformed(ActionEvent evt) {
     if (evt.getActionCommand().equals("doNuovoCliente")) {
	setVisible(false);
         new NuovoCliente().setVisible(true);
     }
     ...
   }
   private JButton createJbutton() {
     JButton button = new JButton("Nuovo Cliente");
     button.setActionCommand("doNuovoCliente");
     button.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent evt) {
         MiaClasse.this.actionPerformed(evt);
       }
     });
     toolBar.add(button);
   }
...
}
Una cosa che faccio spesso, ma che è prona ad errori a runtime se il 
codice non è "ordinato", e' quella di mettere come actionCommand il nome 
di un metodo da eseguire, con questa tecnica:
String cmd = evt.getActionCommand();
Method method = MiaClasse.class.getDeclaredMethod(cmd, (Class[])null);
method.invoke(MiaClasse.this, (Object[])null);
Con i dovuti try/catch, che presuppone di chiamare metodo senza 
argomenti, tipo:
  private void doNuovoCliente()
Questa tecnica ha come scopo principale, quello di "alleggerire" il 
metodo actionPerformed da potenzialmente interminabili switch/if-else-if 
ed incapsulare il codice da eseguire in metodi separati ognuno con la 
propria responsabilità.
 
Da notare che ciò che fai nel metodo actionPerformed, viene eseguito da 
una particolare thread che "consuma" gli eventi presenti nella coda 
degli eventi, quindi devi essere consapevole che tutto cio' che esegui, 
viene eseguito in modo sincrono, quindi, allo scopo di permettere che un 
determinato evento finisca, venga consumato, e che la thread di cui 
sopra continui a processare gli eventi in coda, potresti accodare le 
azioni che produci mediante il metodo statico 
SwingUtilities.inkokeLater, ad esempio:
       public void actionPerformed(ActionEvent evt) {
	SwingUtilities.inkokeLater(new Runnable() {
           public void run() {
             MiaClasse.this.actionPerformed(evt);
           }
	});
       }
 
Hai anche la possibilità di uscire e rientrare nella coda degli eventi, 
eseguendo il codice in una thread separata e rientrando tramite il 
metodo SwingUtilities.inkokeAndWait, con la stessa tecnica. In generale, 
è sempre meglio creare nuovi oggetti swing o awt, dalla thread degli 
eventi, mentre e' spesso meglio eseguire azioni di lunga durata, o 
semplicemente dall'esito incerto, in una thread separata. I casi possono 
essere molteplici, uno tra tutti potrebbero essere i metodi di accesso 
ad un database. In questo caso particolare, l'accesso al database, devi 
essere consapevole delle capacità del database sotteso, per cui potrebbe 
essere auspicabile accedere al db da una thread unica. In tal caso puoi 
utilizzare un executor single thread.
Ad esempio:
ExecutorService databaseService = Executors.newSingleThreadExecutor();
...
private void createNuovoCliente() {
    Future<Cliente> future = databaseService.submit(
      new Callable<Cliente>() {
       public Cliente call() {
           // crea un nuovo cliente nel db e ritorna il
           // bean di dati inizializzato con la chiave
           // del nuovo record creato
           Cliente cliente = ....;
           return cliente;
        }
      });
      try {
        Cliente cliente = future.get();
      } catch(Exception e) {
        ...
      }
}
questa tecnica accede al database in modo sincrono, quindi chi chiama il 
metodo createNuovoCliente aspetta. L'effetto visivo e' che se il metodo 
createNuovoCliente viene eseguito dall'ActionListener del bottone, il 
bottone risulta premuto finche' il metodo non finisce.
 
Altra tecnica, asincrona, potrebbe essere:
 
private void createNuovoCliente() {
    final Window
      window = SwingUtilities.windowForComponent(MiaClasse.this);
      window.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    databaseService.execute(
      new Runnable() {
        public void run() {
           // crea un nuovo cliente nel db e ritorna il
           // bean di dati inizializzato con la chiave
           // del nuovo record creato e crea un nuovo oggetto gui
           final Cliente cliente = ....;
           SwingUtilities.invokeAndWait(
             new Runnable() {
               public void run() {
                 MiaClasse.this.setVisible(false);
                 new NuovoCliente(cliente).setVisible(true);
                 window
                  .setCursor(
                     Cursor
                     .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
               }
             }
           );
        }
      });
}
 
Questa tecnica assolve ai due obiettivi di accedere al db tramite una 
singola thread e creare oggetti gui tramite la thread degli eventi 
swing. Inoltre libera la thread swing permettendo di esaurire la coda.
Nota il modificatore final, in questo caso serve per poter utilizzare 
l'oggetto cliente e window nei metodi delle classi inner.
L'effetto visivo e' che se il metodo createNuovoCliente viene eseguito 
dall'ActionListener del bottone, il bottone risulta rilasciato anche 
durante l'esecuzione. A questo punto l'utente viene notificato che c'e' 
qualcosa da aspettare mediante la modifica del cursore: 
Cursor.WAIT_CURSOR mostra un'iconcina che gira al posto del puntatore 
del mouse, Cursor.DEFAULT_CURSOR rimette a posto il puntatore del mouse.
Nota anche il metodo statico SwingUtilities.windowForComponent, che 
rintraccia la Window piu' prossima che contiene il componente 
specificato, uno qualsiasi nella gerarchia dei Container.