Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passare da un JPanel ad un altro...

489 views
Skip to first unread message

Daniele Volpe

unread,
Nov 5, 2012, 8:57:37 AM11/5/12
to
Ciao a tutti, vorrei creare un'applicazione così strutturata :

All'avvio dell'applicazione ho un JFrame che viene visualizzato con al suo interno un JPanel (creato in una classe a parte ma dichiarato all'interno della classe del JFrame).
Da questa schermata si effettua il login e se tutto va a buon fine vorrei sostituire il pannello attuale utilizzato per il login, inizializzandone uno nuovo (creato in un'altra classe) senza utilizzare il CardLayout... voglio gestire tutto io manualmente.

Quindi ho 3 classi... :
- 1 classe che estende JFrame (che sarebbe quella principale)
- 1 classe che estende JPanel (che sarebbe quella di Login contenuta nel JFrame)
- 1 classe che estende JPanel (che sostituisce il JPanel utilizzato nella fase di Login, contenuto nel JFrame principale)

In parole povere vorrei fare in modo che il JFrame abbia sempre e solo 1 JPanel da gestire... che deve essere creato di volta in volta con il seguente comando:
panel = new (Nome della classe creata che estende JPanel)();

Questo comunque è il JFrame che ho creato :

--------------------------------------------------------------------------------
public class Main extends JFrame {

private JPanel panel;

public static void main(String[] args) {
try {
Main window = new Main();
window.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}

public Main() {
this.setTitle("Prova");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(100, 100, 260, 300);
this.setResizable(false);
panel = new Login();
this.setContentPane(panel);
}
}
--------------------------------------------------------------------------------

Questo è il codice del JPanel di Login che viene visualizzato all'inizio :

--------------------------------------------------------------------------------
public class Login extends JPanel {
private JTextField jUserField;
private JPasswordField jPasswordField;

public Login() {
this.setLayout(null);
this.setBorder(new EmptyBorder(5,5,5,5));

JButton btnLogin = new JButton("Login");
btnLogin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {

}
});
btnLogin.setBounds(96, 192, 89, 23);
add(btnLogin);

JLabel lblUser = new JLabel("Username");
lblUser.setBounds(21, 96, 74, 14);
add(lblUser);

JLabel lblPassword = new JLabel("Password");
lblPassword.setBounds(21, 129, 74, 14);
add(lblPassword);

jUserField = new JTextField();
jUserField.setBounds(105, 93, 122, 20);
add(jUserField);
jUserField.setColumns(10);

jPasswordField = new JPasswordField();
jPasswordField.setBounds(105, 126, 122, 20);
add(jPasswordField);
}
}
--------------------------------------------------------------------------------

Questo è il codice del JPanel che deve essere visualizzato al posto del vecchio, a login avvenuto :

--------------------------------------------------------------------------------
public class SecurityContainer extends JPanel {

public SecurityContainer() {
this.setLayout(null);
this.setBorder(new EmptyBorder(5,5,5,5));

JButton btnSalva = new JButton("Salva");
btnSalva.setBounds(102, 253, 89, 23);
add(btnSalva);

}
}
--------------------------------------------------------------------------------

Come faccio a sostituire il panel contenuto nella classe Main (JFrame) con quello nuovo (SecurityContainer) quando dalla classe Login (JPanel) clicco sul pulsante "Login" ?

Ho provato con il getParent() ma non è che ci abbia capito molto... stavo pensando anche di passare la classe Main nel costruttore della classe Login come parametro "final"....
Help me :)

Dr.Ugo Gagliardelli

unread,
Nov 5, 2012, 9:30:48 AM11/5/12
to
il 05.11.2012 14:57, Scrive Daniele Volpe 96485068:
Per quanto possa aver capito, dovresti utilizzare di nuovo il metodo
setContentPane ad esempio nel corpo del metodo actionPerformed in questo
modo;
final JPanel p = this;
public void actionPerformed(ActionEvent e) {
boolean validLogin = // qui occorre validare il login
if (validLogin) {
// il metodo getParent() ritorna null finche'
// il panel non e' stato aggiunto ad un contenitore
Container c = p.getParent();
if (c != null && (c instanceof JFrame)
((JFrame)c).setContentPane(new SecurityContainer();
}
}

Daniele Volpe

unread,
Nov 5, 2012, 4:12:51 PM11/5/12
to
Grazie per la risposta.

Si è proprio quello che vorrei fare, ho provato a modificare il codice all'interno dell'evento, ma non mi entra nell'if in quanto il container non è un'istanza di JFrame.

Mettendo le seguenti 2 righe di stampa :
System.out.println(c.getComponentCount());
System.out.println(c.getName());

Mi stampa rispettivamente :
1
null.layeredPane

Dr.Ugo Gagliardelli

unread,
Nov 6, 2012, 6:14:42 AM11/6/12
to
il 05.11.2012 22:12, Scrive Daniele Volpe 107774828:
> Grazie per la risposta.
>
> Si è proprio quello che vorrei fare, ho provato a modificare il codice
> all'interno dell'evento, ma non mi entra nell'if in quanto il container
> non è un'istanza di JFrame.
Hai ragione, sono stato frettoloso. In effetti il JPanel non viene
aggiunto al JFrame ma al suo root container, per cui dovresti rimuovere
il vecchio JPanel ed aggiungere il nuovo probabilmente così:

final JPanel p = this;
public void actionPerformed(ActionEvent e) {
boolean validLogin = // qui occorre validare il login
if (validLogin) {
// il metodo getParent() ritorna null finche'
// il panel non e' stato aggiunto ad un contenitore
Container c = p.getParent();
if (c != null) {
c.remove(p);
c.add(new SecurityContainer());
}
}
}


Un'altra cosa che mi era sfuggita: utilizzando il metodo setContentPane,
e' opportuno che il JComponent utilizzato sia opaque, per rispettare
l'architettura di painting dei componenti swing che pretende che almeno
un componente opaque nella gerarchia dei contenitori , quindi nella
costruzione dei tuoi oggetti Login e SecurityContainer dovresti
utilizzare setOpaque(true).

In definitiva invece di utilizzare setContentPane(panel), utilizzerei
invece getContentPane().add(panel), rimanendo il resto invariato.
In pratica utilizzando il content pane creato dal costruttore di JFrame.

Daniele Volpe

unread,
Nov 6, 2012, 5:53:31 PM11/6/12
to
Ho apportato le ultime modifiche, il programma non va in errore ma cliccando sul pulsante di Login non mi cambia il pannello.
Sto provando a fare un po di prove :)

Daniele Volpe

unread,
Nov 7, 2012, 12:33:27 PM11/7/12
to
Ho risolto, dovevo dare il "revalidate()" :)
Grazie ancora per l'aiuto.

stefano Cambazzu

unread,
Mar 23, 2023, 1:57:29 PM3/23/23
to
Ciao a tutti ,
Ho creato un classe principale

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;

import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;






public class fantasy1 extends JFrame {
public static Clip audio;

public static void main(String[] args) {



colonnasonora("./sound/storia.wav");

JFrame myFrame = new JFrame("Fantasy 1");


//Se larghezza 768 --> 16 *48 (Muro) --> 768 - Altezza 576 --> 48 *12

myFrame.setSize(728, 455); // 768 * 576 -> risoluzione dell'immagine oelemento
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setLocationRelativeTo(null);
myFrame.setResizable(false);
// vorrei scrivere se premo la barra spaziatrice carichi l'immagine statica 1
la seconda volta immagine 2 la terza immagine 3
La 4 volta entra nel gioco e carico la classe dedicata GameFrame
GameFrame prende il controllo della tastiera programmata per il player
myFrame.add(new cover()); // Copertina
//myFrame.add(new GameFrame()); // Gioco

myFrame.setIconImage(new ImageIcon("./img/ico.png").getImage());
myFrame.setVisible(true);




}

public static void colonnasonora ( String musica){


try {
audio = AudioSystem.getClip();

audio.open(AudioSystem.getAudioInputStream(new File(musica)));
audio.loop(Clip.LOOP_CONTINUOUSLY);
audio.start();
} catch (Exception e) {
System.out.println(e);
}
}


}


Ho la necessità il programma parte con il panello definito sulla classe cover
questa deve rimanere in ascolto dei tasti.
se non viene premuto nulla la cover carica slide immagini a ripetizione.
Alla pressione del tasto "Space"
Viene caricata un immagine statica 1
la seconda volta un immagine statica 2
alla terza un immagine statica 3
alla quarta volta il programma passa dal panello definito nella classe cover alla classe GameFrame.
Questa classe rimane in ascolto dei tasti a seconda del tasto premuto muove il player
ecco un seudo codice

usa cosa del genere
myFrame.add(new cover()); // Copertina caricata all'avvio dell'applicazione
cont= 0;
if (e.event =='space' ) {
if ( cont ==0) {
loadimage1;
cont= cont+1;
} esle if ( cont ==1) {
loadimage2;
cont= cont+1;
} esle if ( cont ==2) {
loadimage3;
cont= cont+1;
} else
myFrame.add(new GameFrame()); //Modifico il panello e prendo controllo dei tasti
// attiva tasti gestione player
}

Come faccio a cambiare il panello in fase di avvio e gestire i tasti in modo che all'inizio vengono rilevati dalla classe cover è successivamente viene caricata la classe GameFrame cambiando evento tasti dedicati al player?

Grazie mille
0 new messages