Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16

    jCheckBox a runtime con evento

    Salve a tutti,
    ne approfitto per salutare la comunity dato che sono nuovo, sia di questo forum che di Java.

    Pongo subito la mia domanda:
    realizzo una gui con la collocazione a runtime di un certo numero di jCheckBox definite da un'interrogazione ad un database, alcune di queste ultime dovrebbero implementare delle "actionPerfomed", ma non so se la cosa sia fattibile e se si, come.

    Eternamente grato a chi mi risponderà

    Di seguito il codice in questione:


    Premetto che le classi di supporto: MyScrollPane e MyPanel non sono altro che delle estensioni delle classiche componenti in cui definisco solo le "preferenze"

    codice:
    package Scroller;
    
    import java.awt.BorderLayout;
    import java.awt.Font;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JSeparator;
    
    public class Scroller extends JFrame{
        private Scroller scrollpane;
        static Connection conn;
    
        
        public Scroller(){
        
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
            setBackground(new java.awt.Color(0, 240, 0));
            setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
    
            setLocation(600, 10);
            setMinimumSize(new java.awt.Dimension(300, 700));
            setPreferredSize(new java.awt.Dimension(320, 700));
            this.setVisible(true);
        }
        
        public static void main(String[] args) throws SQLException, ClassNotFoundException{
            Scroller scrollpane = new Scroller();
            
            MyPanel p = new MyPanel();
            MyScrollPane sp = new MyScrollPane(p);
            ResultSet rs=null;
            Statement st=null;
    /*
     *
     * Database interrogation and connection
     *
     */        
            String query="select name from base;";
            String query2="select name from extra;";
           
            Class.forName("org.sqlite.JDBC");
            conn=DriverManager.getConnection("jdbc:sqlite:optionals.sqlite");        
    
            st = conn.createStatement();
            rs = st.executeQuery(query);
    /*-- END DB SECTION --*/        
            
    /*-- COMPONENT POSITIONING --*/ 
        //BASE COMPONENT
        //BASE CONFIGURATION LABEL    
            JLabel base=new JLabel("Base Configuration:", JLabel.LEFT);
            base.setFont(new Font("Tahoma",Font.BOLD,12));
            base.setForeground(new java.awt.Color(38, 172, 210));
            p.add(base);
        //jCHECKBOX LIST
            while(rs.next())
            {
                String var1 = rs.getString("name");
                p.add(new JCheckBox(var1));
            } 
            JSeparator jsep=new JSeparator();
        //END BASE COMPONENT
        //SEPARATOR
            p.add(jsep);
        //EXTRA COMPONENT
        //EXTRA COMPONENT LABEL
            JLabel extra=new JLabel("Extra Optionals:", JLabel.LEFT);
            extra.setFont(new Font("Tahoma",Font.BOLD,12));
            extra.setForeground(new java.awt.Color(38, 172, 210));
            p.add(extra);
        //REDEFINITION OF QUERY
            rs = st.executeQuery(query2);
        //jCHECKBOX LIST
            while(rs.next())
            {
                String var1 = rs.getString("name");
                p.add(new JCheckBox(var1));
            }       
        //END BASE COMPONENT
            
        //ADDING SCROLLPANE TO jFRAME
            scrollpane.add(sp, BorderLayout.CENTER);    
        }
    }
    Domanda strana: Durante l'esecuzione mi si apre la finestra ma le componenti appaiono solo se compio un'azione tipo resize sulla finestra stessa. Da cosa dipende?

    Ancora mille grazie a tutti!
    Palf

  2. #2
    Per il resize:
    Hai bisogno di un revalidate() e un repaint().
    Quando fai il resize del JFrame automaticamente il sistema richiama il repaint().
    Devi invocare il metodo quando sono stati messi i checkbox.

    Per le JCheckBox:
    una cosa che potesti fare è dichiararti un array di JCheckBox, capire quanti te ne servono e con un for ciclarti su ogni checkbox per invocare la classe che si occuperà della listener.

    Non è proprio facilissimo se non conosci bene java.
    I computer sono incredibilmente veloci, accurati e stupidi.
    Gli uomini sono incredibilmente lenti, inaccurati e intelligenti.
    Insieme sono una potenza che supera l'immaginazione.

    A.Einstein

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Per il problema della visualizzazione dei componenti, tutto il problema è dovuto al fatto che effettui un setVisible( true) prima di aggiungere i componenti alla finestra. Il metodo setVisible( true) dovrebbe essere sempre l'ultima istruzione da chiamare, quando tutti i componenti sono stati aggiunti al contenitore.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  4. #4
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Grazie per le dritte ragazzi, ne farò tesoro!
    Ho sistemato un bel setVisible subito dopo la sua allocazione nel frame ed ho risolto. (comunque la lezione di Schumy mi è utile)

    Per i checkbox comprendo a pieno la difficoltà: in effetti li alloco caricando la lista dei nomi da un db SQLite (derby l'ho maledetto troppo ) e l'evento legato ad alcuni di essi dovrà poi causare effetti su un secondo Jpanel (che verrò poi).
    Un test statico l'ho già fatto e funziona bene ma credo che con l'instanziamento dinamico degli oggetti, oltre ad avere una miriade di controlli in più, mi serva uno strumento (uso un termine generico) in grado di rilevare le checkbox presenti sul pannello.

    Ho appena testato il metodo getComponentCount(); e mi ha riportato l'esatto numero di oggetti presenti nel panel che contiene i jCheckBox.

    Ho aggiunto questi statements per testare la fattibilità:
    codice:
    ...
            scrollpane.add(sp, BorderLayout.CENTER);
            scrollpane.setVisible(true);
            System.out.println(p.getComponentCount());
            System.out.println(p.getComponent(5).toString());
    ...
    Debbo dire che il numero di componenti è esatto, mi salta anche le label (il che mi facilita il compito), tuttavia mi servirebbe una bella dritta per cercare di gestire gli eventi su questi ultimi oggetti.

    Al massimo, se prorpio non riesco prendo per buona la soluzione di shumy rendendo la cosa statica, anche se poi il db di supporto perde molta della sua utilità...

  5. #5
    io non parlando di soluzione statica...ma a runtime ti conti il numero di elementi presi dal DB e te li istanzi come numero di elementi del vettore di JCheckBox.
    Per riconoscerli puoi usare mi sembra il setName...
    oggi purtroppo non ho tempo magari domani riesco a farti un piccolo esempio.

    Ciao.
    I computer sono incredibilmente veloci, accurati e stupidi.
    Gli uomini sono incredibilmente lenti, inaccurati e intelligenti.
    Insieme sono una potenza che supera l'immaginazione.

    A.Einstein

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Schumy ti ringrazio per pazienza e disponibilità!
    Sono arrivato alla tua stesa conclusione:
    [list=1][*]carico a runtime dal db[*]istanzio l'oggetto checkbox includendogli l'action in creazione[*]lo includo nell'array (magari uso il nome come indice )[/list=1]

    Ora mi sovviene un dubbio solamente: siccome l'azione del checkbox dovrà gestire un altro checkbox, anch'esso caricato a runtime (ma sono univocamente collegati tra loro: in pratica è una mutua esclusione di check status), potrò gestire la cosa utilizzando l'array (inteso come campo + indice)?

    So che la richiesta è bella tosta ma mi piace fare le cose in modo "elegante" (per le mie conoscenze).

    Pertanto sono riuscito a gestire un minimo di evento come mostrato nel codice seguente:
    codice:
        //jCHECKBOX LIST
            while(rs.next())
            {
                String var1 = rs.getString("name");
                jc=new JCheckBox(var1);
    
                if("Speakers".equals(var1)){
                    jc.addActionListener(new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent e)
                      {
                          //Execute when button is pressed
                          System.out.println("You checked Speaker");
    
                      }
                    });     
                      p.add(jc);
                }
                else
                p.add(jc);
            }       
            
        //END EXTRA COMPONENT
        //ADDING SCROLLPANE TO jFRAME
    Se la cosa non dovesse andare mi vedrò costretto a creare tutti i CB staticamente, tuttavia la strada del runtime mi sembra avvincente!

    Allego continuamente il codice, ad ogni piccolo passo, perchè così credo di essere più chiaro, ma soprattutto perchè possa risultare da esempio per chi può avere un problema simile al mio, almeno non si esaurisce a trovare soluzioni online come ho fatto io

  7. #7
    Allora considerando il fatto che l'avrei fatto in modo più pulito.
    Potevi costruire una classe per la gestione del DB, una per l'interfaccia grafica, una per il listener e un'altra per i relativi controlli così da modellare e rendere più semplice e intuitivo il tuo sistema.
    Prima mi sono sbagliato è più semplice gestire il tutto con il setActionCommand, metodo che ogni componente possiede e poi nel actionPerformed recuperarti il valore visto che l'ActionEvent ha la possibilità di recuperarlo.
    Cmq passando alla tua richiesta si l'unico modo è comandare il tutto tramite array di CB, il problema è che per come l'hai modellato è un pò problematico

    io avrei fatto così

    codice:
    //nella classe che gestisce la grafica ad esempio GuiCheckBox
    //classe per la gestione del DB
    DBLink db =new DBLink();
    int element=db.contaElementi();
    
    cb=new JCheckBox[element];
    
    for(int i=0; i<element; i++){
       cb[i]=new JCheckBox();
       cb[i].setActionCommand("cb"+String.valueOf(i));
       cb[i].addActionListener(new ControlBox(this));
    }
    ControlBox
    codice:
    public ControlBox implements ActionListener {
      //al limite puoi portare qualche variabile che ti server tramite il costruttore 
       private GuiCheckBox box;
       
      public ControlBox(GuiCheckBox box) {
         this.box=box;
       }
    
       public void actionPerformed(ActionEvent e){
        String tmpvalue=e.getActionCommand();
    
        //avendo il valore della variabile con una struttura if-else if-else
        //o switch case puoi fare le tue assegnazioni visto che ti sei portato
       // il riferimento alla classe  che comanda la tua GUI 
       
    .....
    ....
    ...
    
       }
    }
    Almeno io l'avrei pensata e modellata in questo modo ma ci sono innumerevoli modi per gestire la situazione sicuramente anche più corretta della mia.

    se ti serve una mano sono qui....
    Ciao.
    I computer sono incredibilmente veloci, accurati e stupidi.
    Gli uomini sono incredibilmente lenti, inaccurati e intelligenti.
    Insieme sono una potenza che supera l'immaginazione.

    A.Einstein

  8. #8
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Grazie mille shumy!
    Oggi vedrò di metter su la cosa, poi ti faccio sapere.

    Ho scritto tutto il codice in un solo file perchè dovevo velocemente testare il db (i commentoni enormi mi servono visivamente per identificare le classi quando asseblerò il progetto finale ), ora sono passato ad un'altra parte della gui, ma resta ovvio che dovrò strutturare le classi per il db e per i listener, ho ancora molti retaggi della mia formazione (di base sono un sistemista linux ) e mi sto applicando su java da meno di dieci giorni (incluso il tempo speso per bestemmiare win8 e Derby - circa 2gg ) ed ammetto che mi piace molto come linguaggio di programmazione

    Ancora grazie per la disponibilità
    Buon inizio di giornata anche a te
    Use the fork() Luke!

  9. #9
    Se sei solamente da 10 gg su Java stai facendo veramente dei passi da gigante...
    I computer sono incredibilmente veloci, accurati e stupidi.
    Gli uomini sono incredibilmente lenti, inaccurati e intelligenti.
    Insieme sono una potenza che supera l'immaginazione.

    A.Einstein

  10. #10
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Rieccomi a lavorare sui checkbox...

    Ho sistemato un po' il codice poichè, come giustamente dicevi, è più pulito ed utile e visto che oramai mi accingo ad unire le componenti per testarle assemblate. In pratica il mio progetto prevede un Jframe iniziale che presenta una schermata con 12 jbutton piazzati sotto ad un'immagine (mi sono cimentato con: Jpanel con sfondi, JLabel trasparenti, GridBagLayout[sia nel pannello inferiore che nei JButton]) tutti con un listener in ascolto sui bottoni che a seconda del pulsante premuto e mi apre una nuova JFrame portando con se il source in quanto la label del JButton (ogni JButton ha una immagine con jlabel per didascalia) è la chiave per la query che genera l'array dei checkbox. (faccio le cose sempre belle complesse)

    Ora però sto bestemmiando per una sciocchezza che, in altro progetto mi aveva funzionato:
    codice:
    //rs è Resultset ovviamente
    rs.last();
    int i=rs.getRow();
    rs.beforefirst();
    l'errore generato è ResultSet is TYPE_FORWARD_ONLY
    Spero che l'errore non derivi da SQLite...

    per cui sono costretto a fare sto scempio...
    codice:
    Connection conn = DbManager.connect(); //Invoco la connessione nella classe DbManager
    st = conn.createStatement();//Creo lo statement
    //Eseguo la query e riporto i risultati
    rs=DbManager.ask(conn, "nome tabella", "chiave ricerca");
    System.out.println(DbManager.getNumElementi(rs));
    rs=DbManager.ask(conn, "nome tabella", "chiave ricerca");//di questo me ne vergogno!
    è normale che debbo definire il createStatement sia qui che nella classe di gestione del db? Se da qui lo levo non funziona più.

    Allego la classe per gestire il db (ogni dritta è ben accetta )

    codice:
    public class DbManager{
    
        public static Connection connect() throws SQLException, ClassNotFoundException{
            Class.forName("org.sqlite.JDBC");
            Connection conn=DriverManager.getConnection("jdbc:sqlite:./optionals.sqlite");         
            return conn;    
        }
        
        public static ResultSet ask(Connection conn,String db,String key) throws SQLException{
            Statement st=null;
    
            if(conn!=null){
            st=conn.createStatement();
            String query="select name,"+key+" from "+ db +" where "+key+"!='n';";
            return(st.executeQuery(query));
            }
            else{
                System.out.println("Connessione nulla!");
                return null;
            }
        }
        
        public static int getNumElementi(ResultSet rs) throws SQLException{
            int i=0;
    
            while(rs.next())
                i++;
    
            return i;
        }
    
        public static void closeConn(Connection conn) throws SQLException{
            if(conn!=null){
                conn.close();
                System.out.println("Connessione chiusa'!");
            }
        }
    }
    Più che altro mi chiedo come possa fare con classi non static: netbeans mi obbliga quasi a farle così...
    Nel frattempo convengo che creare l'array di cb è la soluzione migliore, lo creerò nella classe di controllo dei checkbox così come mi hai suggerito. (ed ancora grazie)

    Grazie in anticipo per le risposte
    Palf
    Use the fork() Luke!

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.