Collections (Java)

DamianFox
Salve a tutti!!
Sono uno studente che studia informatica al primo anno e venerdi 8 luglio ho l'esame di Programmazione 2 (Java).
In questi giorni sto tentando di fare l'esercizio che il docente ha dato al primo appello.

In questo programma c'è un finestra costituita da due pannelli: quello in alto ha tre bottoni (reset, mescola, stampa) mentre quello al centro è costituita da una serie di pannelli che formano una scacchiera (ho usato l'arraylist per fare la griglia di pannelli).

Premendo il bottone "mescola" i pannelli verranno disposti in maniera casuale; il metodo che conosco per fare questo è usare il metodo "shuffle" presente nella classe Collections, quindi ho creato una classe che estende Collections e implementa ActionListener:

E qui arriva il problema: :? la classe Collections ha il costruttore privato e quindi scrivendo il costruttore della mia classe mi dà errore :"Collections() has private access in java.util.Collections"... :o

qualcuno mi può dare una mano a risolvere questo problema??
Grazie!!! :D :D

Risposte
hamming_burst
Ciao,
copia il codice in tag [code] così vediamo.
Dipende da come hai dichiarato gli oggeti nella tua classe.

apatriarca
Collections ha solo metodi statici e non ha quindi senso creare una nuova istanza della classe. Questo è il motivo per cui ha il costruttore privato. Deve essere usata come Math, nel tuo caso:
Collections.shuffle(list);

DamianFox
Il problema della Collections sono riuscito a risolverlo ma adesso mi compare un problema a run-time.
Vi scrivo il testo di tutto l'esercizio perchè ci sono punti non chiari:

Costruire un'applicazione che mostra una finestra (che all'inizio deve avere dimensioni 400x400) contenente:
- un pannello centrale su cui apparirà un grafica
- tre bottoni: RESET, MESCOLA, STAMPA
Nel seguito le sigle C1, C2, C3, C4 indicano 4 diversi colori a vostra scelta.

1. Nel pannello centrale dovrà essere presente una scacchiera di componenti rettngolari, nel seguito chiamati RETT (io ho usato una griglia di pannelli).
2. I RETT sono inizialmente di diversi colori (C1 e C2) disposti in modo alternato.
3. Quando si clicca su RETT di colore C1, questo cambia colore (passando da C1 a C3e viceversa).
4. Quando si clicca su RETT di colore C2, questo disegna in colore C4 un ovale inscritto in RETT. Il click successivo torna allo stato senza ovale, e il ciclo si ripete.
5. Dopo 4 click su un RETT, questo diventerà un elemento passivo, smettendo di cambiare il suo stato.
6. Il bottone STAMPA stampa in console lo stato di tutti i RETT.
7. Un bottone RESET ripristinerà la situazione iniziale.
8. Un bottone MESCOLA cambierà in modo completamente casuale l'ordine con cui i RETT sono disposti sulla scacchiera.

Di seguito vi metto il codice che ho scritto finora:

La finestra principale:
 public class MyFrame {
    JFrame f = new JFrame("Esercizio Esame");
    JPanel northPanel = new JPanel();
    JButton reset = new JButton("RESET");
    JButton mescola = new JButton("MESCOLA");
    JButton stampa = new JButton("STAMPA");
    GraphicsPanel centerPanel = new GraphicsPanel(mescola);
    JPanel firstPanel = new JPanel();
    JPanel secondPanel = new JPanel();
    JLabel c1 = new JLabel("C1=nero");
    JLabel c2 = new JLabel("C2=verde");
    JLabel c3 = new JLabel("C3=rosso");
    JLabel c4 = new JLabel("C4=blu");
    
    public MyFrame(){
        initFrame();
        initNorthPanel();
        initFirstPanel();
        initSecondPanel();
    }
    
    public static void main(String a[]){
        MyFrame myFrame = new MyFrame();
    }

    private void initFrame() {
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400,400);
        Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension fs = f.getSize();
        f.setLocation((ss.width-fs.width)/2,(ss.height-fs.height)/2);
        f.setVisible(true);
        f.setLayout(new BorderLayout());
        f.add(northPanel,BorderLayout.NORTH);
        f.add(centerPanel,BorderLayout.CENTER);
    }

    private void initNorthPanel() {
        northPanel.setLayout(new GridLayout(1,2));
        northPanel.add(firstPanel);
        northPanel.add(secondPanel);
    }

    private void initFirstPanel() {
        firstPanel.add(reset);
        firstPanel.add(mescola);
        firstPanel.add(stampa);
                
    }

    private void initSecondPanel() {
        secondPanel.setLayout(new GridLayout(4,1));
        c1.setHorizontalAlignment(JLabel.CENTER);
        c2.setHorizontalAlignment(JLabel.CENTER);
        c3.setHorizontalAlignment(JLabel.CENTER);
        c4.setHorizontalAlignment(JLabel.CENTER);
        secondPanel.add(c1);
        secondPanel.add(c2);
        secondPanel.add(c3);
        secondPanel.add(c4);
        
    }
}


Il pannello centrale dove c'è la grafica:
public class GraphicsPanel extends JPanel{
   List coll;
   Iterator iter;
   JButton buttonMescola;
   Rett ret;
   RettOval retOval;
    
    
    public GraphicsPanel(JButton buttonMescola){
        this.setBackground(Color.WHITE);
        this.setLayout(new GridLayout(3,3));
        this.buttonMescola = buttonMescola;
        
        coll = new ArrayList();
        
        
        initChessPanel();
        rettAction();
        this.buttonMescola = buttonMescola;
        
        
    }

    private void initChessPanel() {
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if((i % 2 == 0)&&(j % 2 == 0)){
                  ret = new Rett();
                  ret.setBackground(Color.BLACK);
                  coll.add(ret);
                }
                
                if((i%2==0)&&(j%2!=0)){
                  retOval = new RettOval();
                  //retOval.setBackground(Color.GREEN);
                  coll.add(retOval);
                }
                if((i%2!=0)&&(j%2!=0)){
                  ret = new Rett();
                  ret.setBackground(Color.BLACK);
                  coll.add(ret);
                }
                
                if((i%2!=0)&&(j%2==0)){
                  retOval = new RettOval();
                  //retOval.setBackground(Color.GREEN);
                  coll.add(retOval);
                 }
                
            }
        }
        
        panelAdd();
    }

    private void panelAdd() {
        iter = coll.iterator();
        this.removeAll();
        
        while(iter.hasNext()){
            JPanel element = (JPanel) iter.next();
            this.add(element);
        }
    }

    private void rettAction() {
        ButtonAction buttonAction = new ButtonAction(coll,ret);
        ButtonAction buttonAction2 = new ButtonAction(coll,retOval);
        buttonMescola.addActionListener(buttonAction);
        buttonMescola.addActionListener(buttonAction2);
    }

    
    
}


public class RettOval extends Rett implements MouseListener{
    Dimension ps;
    
    int counter=0;
    int width=0;
    int height=0;
    
    
    
    public RettOval(){
        
        ps = this.getSize();
        
        this.addMouseListener(this);
        
    }
    
    @Override
    public void paintComponent(Graphics g){
                
        g.setColor(Color.GREEN);
        g.fillRect(0,0,this.getWidth(),this.getHeight());
           
        g.setColor(Color.BLUE);
        g.fillOval(0,0,width,height);
           
           
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if((width==0)&&(height==0)){
           width = ps.width;
           height = ps.height;
        }
        if((width==ps.width)&&(height==ps.height)){
           width = 0;
           height = 0;
        }
        this.repaint();
        
        
        
        
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        
    }

    @Override
    public void mouseExited(MouseEvent e) {
        
    }
    
}


public class Rett extends JPanel{
    
    public Rett(){
          panelRetAction();
          
    }    

    private void panelRetAction() {
          RettAction retAction = new RettAction(this);
          this.addMouseListener(retAction);
    }
    
}



public class RettAction extends MouseAdapter {
    Rett rettangolo;
    
    
    public RettAction(Rett rettangolo){
        this.rettangolo = rettangolo;
        
        
    }

    @Override
    public void mousePressed(MouseEvent e){
        Color colore = rettangolo.getBackground();
        Dimension ps = rettangolo.getSize();
        
        if(colore == Color.BLACK){
          rettangolo.setBackground(Color.RED);
          
        }
        
        if(colore == Color.RED){
          rettangolo.setBackground(Color.BLACK);
          
        }
    }
    
}


 public class ButtonAction implements ActionListener{
    JPanel componente;
    List coll;
    Iterator iter;
    
    
    
    public ButtonAction(List coll,JPanel componente){
        this.componente = componente;
        this.coll = coll;
        
        iter = coll.iterator();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String s = e.getActionCommand();
        
        if(s.equals("MESCOLA")){
            Collections.shuffle(coll);
            panelAdd();
        }
        
        
    }

    public void panelAdd() {
        
        componente.removeAll();
        
        while(iter.hasNext()){
            componente = (JPanel) iter.next();
            coll.add(componente);
        }
    }
    
}


Il punto 4 non mi funziona, non so dove ho sbagliato..

apatriarca
In che modo non ti funziona il punto 4? Non ti visualizza l'ellisse? Se devo essere sincero utilizzi un metodo abbastanza complicato per impedire che l'ellisse venga disegnato. Fai infatti uso di due variabili che dovrebbero essere uguali a zero quando l'ellisse debba essere disegnata e uguale alla dimensione del pannello in caso contrario. Ma la dimensione del pannello, invece di calcolarla ogni volta che ti serve, la calcoli nel costruttore (in cui la dimensione non è settata non essendo ancora stato eseguito il layout..) e utilizzi sempre quella. Anche se la dimensione fosse già disponibile nel costruttore avresti poi dei problemi nel caso il pannello venisse ridimensionato. La soluzione sarebbe calcolare ogni volta la dimensione, oppure, ancora meglio, utilizzare un semplice booleano per stabilire se disegnare o meno l'ellisse. Qualcosa come il seguente insomma:
public class RettOval extends Rett implements MouseListener{
     int counter=0;

     boolean drawOval;
          
     public RettOval(){
         drawOval = false;
         
         this.addMouseListener(this); 
         
     } 
     
     @Override 
     public void paintComponent(Graphics g){ 
                 
         g.setColor(Color.GREEN); 
         g.fillRect(0,0,this.getWidth(),this.getHeight()); 
         
         if (drawOval) {
             g.setColor(Color.BLUE); 
             g.fillOval(0,0,width,height); 
         }
             
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
         
     } 

     @Override 
     public void mousePressed(MouseEvent e) { 
         drawOval = !drawOval;
         this.repaint(); 
         
         
         
         
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
         
     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
         
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
         
     } 
     
 }

DamianFox
Adesso funziona!! Grazie mille!! Non mi sarebbe mai venuto in mente di usare una variabile booleana..
Comunque per far diventare passivi i pannelli basta che usi un contatore nel metodo mousePressed??
Hai qualche idea per il punto 8??
Ancora grazie dell'aiuto!

DamianFox
Sono riuscito ad implementare il bottone "Mescola", ma non riesco a capire come fare gli altri due. C'è nessuno che può aiutarmi??

Ho modificato la classe "GraphicsPanel" :

public class GraphicsPanel extends JPanel implements ActionListener{
   List coll;
   Iterator iter;
   JButton buttonMescola, buttonReset, buttonStampa;
   Rett ret;
   RettOval retOval;
   
   
   
    
    
    public GraphicsPanel(JButton buttonMescola, JButton buttonReset, 
            JButton buttonStampa){
        this.setBackground(Color.WHITE);
        this.setLayout(new GridLayout(3,3));
        
        this.buttonMescola = buttonMescola;
        this.buttonReset = buttonReset;
        this.buttonStampa = buttonMescola;
       
        coll = new ArrayList();
        
        
        initChessPanel();
        rettAction();
        
        
        
    }

    

    

    private void initChessPanel() {
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if((i % 2 == 0)&&(j % 2 == 0)){
                  ret = new Rett();
                  coll.add(ret);
                }
                
                if((i%2==0)&&(j%2!=0)){
                  retOval = new RettOval();
                  coll.add(retOval);
                }
                if((i%2!=0)&&(j%2!=0)){
                  ret = new Rett();
                  coll.add(ret);
                }
                
                if((i%2!=0)&&(j%2==0)){
                  retOval = new RettOval();
                  coll.add(retOval);
                 }
                
            }
        }
        
        panelAdd();
    }

    private void panelAdd() {
        iter = coll.iterator();
        this.removeAll();
        
        while(iter.hasNext()){
            JPanel element = (JPanel) iter.next();
            this.add(element);
        }
    }

    private void rettAction() {
        buttonMescola.addActionListener(this);
        buttonReset.addActionListener(this);
        buttonStampa.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String s = e.getActionCommand();
        
        if(s.equals("MESCOLA")){
            Collections.shuffle(coll);
            panelAdd();
            this.validate();
        }
        
        if(s.equals("RESET")){
                
        } 
            
        if(s.equals("STAMPA")){
            
        }
    }

    
    
}

DamianFox
c'è qualcuno che può aiutarmi??

apatriarca
In STAMPA dovrai semplicemente fare un ciclo su tutti i pannelli e stampare su console lo stato (il colore). In cosa trovi esattamente difficoltà? Nel caso di RESET conviene forse eliminare dal pannello tutti i sottopannelli e richiamare initChessPanel.

DamianFox
In STAMPA uso un "iterator" quindi? Potresti scrivermi il codice?
Il bottone RESET funzione come hai detto tu.. Grazie!

apatriarca
Un'iteratore va bene:
for (JPanel panel : coll) {
    // ora stampa lo stato di panel.. prendendo il suo tipo e il suo colore
}

Perché il codice che ho scritto funzioni potrebbe essere necessario ridefinire coll come segue:
List<JPanel> coll;

ma ha grossi vantaggi farlo in ogni caso. Non è per esempio più necessario fare un cast con get. In caso tu non volessi farlo devi scrivere qualcosa come:
for (Object obj : coll) {
    JPanel panel = (JPanel) obj;
    // lavora su panel
}

che però mi sembra meno bello.

DamianFox
Io ho fatto così:

if(s.equals("STAMPA")){
          Iterator iter = coll.iterator();
          while(iter.hasNext()){
              Rett rettang = (Rett) iter.next();
              System.out.println(rettang);
              JOptionPane.showMessageDialog(this,rettang); 
          }
          this.validate();
          System.out.println("\n");
          this.validate();
        }


quando premo il tasto "STAMPA" viene visualizzato in console e un'altra finestra lo stato dei pannelli, però quando finiscono le operazioni di stampa la scacchiera si blocca, cioè non posso cambiare il colore dei pannelli, e riesco a farlo solo quando premo il tasto "RESET" o "MESCOLA", perchè?

DamianFox
C'è qualcuno che può rispondermi?

apatriarca
Rett rettang = (Rett) iter.next(); 
System.out.println(rettang); 
JOptionPane.showMessageDialog(this,rettang);

Ma perché stai creando un message dialog?

this.validate(); 
System.out.println("\n"); 
this.validate();

Perché chiami due volte this.validate()?

System.out.println(rettang);

Non hai definito Rett.toString().. Per cui la stringa stampata non mostra per niente lo stato di rettang. Devi fare l'overloading di quella funzione per poter usare semplicemente println.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.