Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it L'avatar di Pierock
    Registrato dal
    Dec 2008
    Messaggi
    102

    [java] problema setSize in extended JDialog

    Salve ragazzi,
    ho la necessità di creare diversi JDialog, tutti quanti accomunati da molte caratteristiche, quali tipo di pulsanti.
    Ho create dunque una classe astratta (AbsDialogOK_ANN) che estende JDialog, la quale ha già tutte le impostazioni che servono;
    look and feel, layout e pulsalti...
    la mia idea è dunque quella di estendere questa classe astratta ogni volta che mi serve un jdialog con pulsanti Ok e Annulla, semplicemente facendo un Override del metodo che restituisce il pannello centrale (getCentralPane).

    Il problema è che la dimesione del jdialog creato attualmente è unica, ovvero il setSize viene effettuato nel costruttore della classe astratta.
    Al fine di rendere la dimensione indipendente, sembrerebbe banale spostare la definizione di questi parametri nelle future classi figlie, ma una volta fatto, si, correggo le dimensioni, ma non so per quale motivo .. quando eseguo una qualsiasi azione, mi risultano nulli tutti gli oggetti (JTextField) che ho creato nel metodo getCentralPane.

    sapreste dirmi come mai succede questo?

    ... se volete aggiungo qualche pezzo di codice per rendere più chiare le cose.

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Pierock Visualizza il messaggio
    ho la necessità di creare diversi JDialog, tutti quanti accomunati da molte caratteristiche, quali tipo di pulsanti.
    Ho create dunque una classe astratta (AbsDialogOK_ANN) che estende JDialog, la quale ha già tutte le impostazioni che servono;
    look and feel, layout e pulsalti...
    Scusa la domanda iniziale: ma JOptionPane non ti bastava? (cioè mettere un pannello come "message" del JOptionPane).

    Quote Originariamente inviata da Pierock Visualizza il messaggio
    la mia idea è dunque quella di estendere questa classe astratta ogni volta che mi serve un jdialog con pulsanti Ok e Annulla, semplicemente facendo un Override del metodo che restituisce il pannello centrale (getCentralPane).
    Di per sé, concettualmente, non fa una piega ma .... c'è un "piccolo" dettaglio che va considerato in questi casi: chi invoca getCentralPane? Lo invoca il costruttore della classe base astratta? Se così bisogna stare mooooolto attenti! Detto in generale: un costruttore non dovrebbe mai invocare un metodo che può essere ridefinito in una sotto-classe. E se proprio è necessario farlo, chi scrive le sotto-classi (e in particolare quel metodo ridefinito) deve essere ben a conoscenza di questo aspetto e scrivere la sottoclasse in modo da non causare problemi.

    Quote Originariamente inviata da Pierock Visualizza il messaggio
    Il problema è che la dimesione del jdialog creato attualmente è unica, ovvero il setSize viene effettuato nel costruttore della classe astratta.
    Al fine di rendere la dimensione indipendente, sembrerebbe banale spostare la definizione di questi parametri nelle future classi figlie, ma una volta fatto, si, correggo le dimensioni, ma non so per quale motivo .. quando eseguo una qualsiasi azione, mi risultano nulli tutti gli oggetti (JTextField) che ho creato nel metodo getCentralPane.
    Se ti basta che la dialog sia alla dimensione minima/giusta cioè i componenti siano alla loro dimensione "preferita", basta fare un pack() sulla dialog.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it L'avatar di Pierock
    Registrato dal
    Dec 2008
    Messaggi
    102
    Ciao andmin,
    grazie mille per l'aiuto...
    Scusa la domanda iniziale: ma JOptionPane non ti bastava? (cioè mettere un pannello come "message" del JOptionPane).
    a dire la verità non avevo pensato ad un JOptionPane, anche perchè in effetti non avevo mai provato ad inserire un pannello come message....
    comunque sia, l'idea della classe astratta nasceva anche in previsione di poterla modificare o renderla più complessa in futuro....
    Ma valuterò di sicuro la tua alternativa.
    Di per sé, concettualmente, non fa una piega ma .... c'è un "piccolo" dettaglio che va considerato in questi casi: chi invoca getCentralPane? Lo invoca il costruttore della classe base astratta? Se così bisogna stare mooooolto attenti!
    Beh, a dire il vero non è invocato "direttamente" dal costruttore... ma dato che il costruttore in questione chiama un metodo che invoca a sua volta getCentralPane,credo che il problema ricada in questo caso.
    Mostrando un po' di codice:
    Questa è l'abstract class
    codice:
    public abstract class AbsDialogOK_ANN extends JDialog{
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	// pannelli
    	private JPanel		_pann	 	= null;
    	protected JPanel	centerJP 	= null;
    	private JPanel 		sud			= null;
    	// JButton
    	private JButton 	_ok			= null;
    	private JButton		_annulla	= null;
    	//
    	protected boolean 	flag		= false;
    	
    	public AbsDialogOK_ANN(String title){
    		super(new JFrame(),title, true);
    		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    		this.setResizable(false);
    		this.setContentPane(this.getJCP());
    		final Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
    		this.setSize(new Dimension(screenSize.width / 2,screenSize.height / 2));
    		this.setLocation((screenSize.width - this.getWidth()) / 2,(screenSize.height - this.getHeight()) / 2);
    		this.setVisible(true);
    	}
    	
    	private JPanel getJCP() {
    		if (this._pann == null) {
    			this._pann = new JPanel();
    			this._pann.setLayout(new BorderLayout());
    //			this._pann.add(this.getNorthPan(), BorderLayout.NORTH);
    			this._pann.add(this.getCenterPan(), BorderLayout.CENTER);
    			this._pann.add(this.getSudPan(), BorderLayout.SOUTH);
    		}
    		return this._pann;
    	}
    	
    	protected JPanel getCenterPan() {
    		if (this.centerJP == null) {
    			this.centerJP = new JPanel();
    			}
    		return this.centerJP;
    	}
    
    
    	private JPanel getSudPan() {
    		if (this.sud == null) {
    			this.sud = new JPanel();
    			this.sud.setLayout(new FlowLayout());
    			this.sud.add(this.getAnnBut());
    			this.sud.add(this.getOKBut());
    		}
    		return this.sud;
    	}
    	private JButton getOKBut() {
    		if(this._ok == null){
    			this._ok = new JButton("Ok");
    			this._ok.addActionListener(new ActionListener(){
    
    
    				@Override
    				public void actionPerformed(ActionEvent e) {
    					AbsDialogOK_ANN.this.actionOkButton();
    				}});
    		}
    		return this._ok;
    	}
    	
    	protected void actionOkButton(){
    		flag=true;
    		dispose();
    	}
    
    
    	private JButton getAnnBut() {
    		if(this._annulla == null){
    			this._annulla = new JButton("Annulla");
    			this._annulla.addActionListener(new ActionListener(){
    				@Override
    				public void actionPerformed(ActionEvent e) {
    				dispose();
    				}});
    			
    		}
    		return this._annulla;
    	}
    	
    	protected boolean isFlag() {
    		return flag;
    	}
    	
    	
    	
    
    
    }
    ..da qui la mia idea era di creare altre classi, alle quali bastava sovrascrivere i metodi protected...
    Tuttavia, oltre al problema delle dimensioni, come hai già compreso, ne ho anche altri, infatti... dopo il dispose di una delle sottoclassi, tutti i metodi getXx mi restituiscono null.
    Es, costruendo una classe in questo modo....
    codice:
    // ti riporto solo le parti "interessanti"
    public class LogInGUI extends AbsDialogOK_ANN
    /...
    @Override
    	public JPanel getCenterPan() {
    		if (this.centerJP == null) {
    			this.centerJP = new JPanel();
    			// ometto la costruz del layout //
    			build.addLabel("UserName", CC.xy(2, 2));
    			build.add(this.getUsernametxt(), CC.xy(4, 2));
    			build.addLabel("Psw", CC.xy(2, 4));
    			build.add(this.getPswtxt(), CC.xy(4, 4));
    			this.centerJP = build.getPanel();
    			this.centerJP.setBorder(BorderFactory.createTitledBorder("User"));
    		}
    		return this.centerJP;
    	}
    
    @Override
    	protected void actionOkButton() {
    		this.credenziali = new String[2];
    		this.credenziali[0] = this.usernametxt.getText();
    		this.credenziali[1] = this.getPsw();
    		super.actionOkButton();
    	}
    public String[] getCredenziali(){
    		return this.credenziali;
    	}
    nel main.... ottengo una NullPointerException.
    codice:
    public static void main(String[] args) {
    		LogInGUI lg = new LogInGUI();
    		String[] cred = null;
    		if(lg.isFlag()){
    			cred = lg.getCredenziali();
    		System.out.println("user: " + cred[0]);
    		}
    Detto in generale: un costruttore non dovrebbe mai invocare un metodo che può essere ridefinito in una sotto-classe. E se proprio è necessario farlo, chi scrive le sotto-classi (e in particolare quel metodo ridefinito) deve essere ben a conoscenza di questo aspetto e scrivere la sottoclasse in modo da non causare problemi.
    .. quindi come posso riadattare le cose in base alle mie esigenze?
    Ovviamente se abbandono l'idea della classe astratta e inglobo tutto, non ho alcun problema...

  4. #4
    Utente di HTML.it L'avatar di Pierock
    Registrato dal
    Dec 2008
    Messaggi
    102
    ... per eliminare la chiamata a getCenterPane dal costruttore, ho fatto questa piccola modifica:

    in AbsDialogOK_ANN
    codice:
    publicAbsDialogOK_ANN(String title){
            super(newJFrame(),title,true);
            this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            this.setResizable(false);
    //      this.setContentPane(this.getJCP());
    //      finalDimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
          //this.setSize(newDimension(screenSize.width /2,screenSize.height /2));
    //      this.setLocation((screenSize.width -this.getWidth())/2,(screenSize.height -this.getHeight())/2);
    //      this.setVisible(true);
        }
    
    protected void init(){
    this.setContentPane(this.getJCP());
    }
    dunque... in LogInGUI
    codice:
    public LogInGUI(){
      super("Login");
      this.init();
    
    }
    
    @Override
    protected void init(){
        super.init();
        final Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        this.setSize(newDimension(screenSize.width /2,screenSize.height /2));
        this.setLocation((screenSize.width -this.getWidth())/2,(screenSize.height -this.getHeight())/2);
        this.setVisible(true);
    }
    sembra si siano risolti i problemi...
    Attendo comunque eventuali consigli

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Pierock Visualizza il messaggio
    a dire la verità non avevo pensato ad un JOptionPane, anche perchè in effetti non avevo mai provato ad inserire un pannello come message....
    comunque sia, l'idea della classe astratta nasceva anche in previsione di poterla modificare o renderla più complessa in futuro....
    Ma valuterò di sicuro la tua alternativa.
    JOptionPane va bene per cose tutto sommato semplici. Se intendi espandere la tua dialog in futuro, es. aggiungere un menù o ad esempio gestire una logica per cui ad esempio il pulsante Ok si abilita solo sotto certe condizioni, allora la creazione della dialog da zero è sì più complessa ma alla lunga ripaga perché hai più controllo.

    Quote Originariamente inviata da Pierock Visualizza il messaggio
    Beh, a dire il vero non è invocato "direttamente" dal costruttore...
    Quello che dicevo io non cambia se la invocazione è diretta o indiretta. Un costruttore non dovrebbe causare (in)direttamente la invocazione di un metodo sovrascritto in una sotto-classe di quella classe.

    codice:
    public class Prova {
        public static void main(String[] args) {
            ClasseBase b = new ClasseDerivata();
        }
    }
    
    abstract class ClasseBase {
        public ClasseBase() {
            test();
        }
        
        protected abstract void test();
    }
    
    class ClasseDerivata extends ClasseBase {
        private String nome = "Paperino";
        
        protected void test() {
            System.out.println("nome = " + nome);
        }
    }
    Prova a dirmi cosa fa questo codice (che a prima vista sembra assolutamente banale e innocuo, specialmente ClasseDerivata) ... e perché ....

    Quote Originariamente inviata da Pierock Visualizza il messaggio
    ... per eliminare la chiamata a getCenterPane dal costruttore, ho fatto questa piccola modifica:
    Ma così il init() della sottoclasse ha troppa "responsabilità", deve invocare super.init() (se te lo dimentichi, nessun errore di compilazione ma poi non ti funziona) e comunque agisce su caratteristiche della dialog che invece non dovrebbe "sapere".
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.