Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 20
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2011
    Messaggi
    33

    Problema grave con grafica JPanel

    Ho una JApplet che contiene un JPanel, che a sua volta ospita diversi componenti e altri due JPanel, sui quali vorrei disegnare due immagini.

    Il problema è che le immagini vengono disegnate ad ogni chiamata di repaint(), ma una frazione di secondo dopo vengono sostituite dal classico colore di sfondo grigio del JPanel.

    Il programma è troppo lungo per effettuare un copia/incolla, ecco le parti principali.
    Le classi coinvolte nella grafica sono tre

    ClassePrincipale extends JApplet
    ChartWindow extends JPanel
    Grafico

    La parte grafica è strutturata come segue

    ClassePrincipale
    Nell' init()
    codice:
    finestraGrafica=new ChartWindow();
    add(finestraGrafica)
    ChartWindow
    codice:
    paintComponent(Graphics g)
    {
      super.paintComponent(g);
      Image immagineGrafico=createImage(grafico.pannelloGrafico.getWidth()
                                      ,grafico.pannelloGrafico.getHeight()); 
      Image immagineVolumi=createImage(grafico.pannelloVolumi.getWidth()
                                      ,grafico.pannelloVolumi.getHeight());
      Graphics2D imgGrafico=(Graphics2D)immagineGrafico.getGraphics();
      Graphics2D imgVolumi=(Graphics2D)immagineVolumi.getGraphics();
      grafico.draw(imgGrafico,imgVolumi,mouseX,mouseY);
    
      ((Graphics2D)grafico.pannelloGrafico.getGraphics()).drawImage(immagineGrafico,0,0,this);
      ((Graphics2D)grafico.pannelloVolumi.getGraphics()).drawImage(immagineVolumi,0,0,this);
    }
    Naturalmente grafico è un oggetto della classe Grafico.
    grafico contiene due JPanel, che vengono aggiunti nel costruttore di ChartWindow assieme ad altri componenti

    codice:
    grafico=new Grafico()
    ................
    add(grafico.pannelloGrafico);
    add(grafico.pannelloVolumi);
    Penso ci sia tutto. Ci sono stato diverse ore dietro ma senza risultati. Se pensate che manchi qualche informazioni scrivetemi senza problemi.
    Grazie per la lettura

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Alcune considerazioni:

    1) Essendo che estendi JApplet, non devi effettuare direttamente l'add sul JApplet, ma sul suo Content-Pane. Quindi, sostituisci
    codice:
    add(finestraGrafica)
    con
    codice:
    getContentPane().add(finestraGrafica);
    Meglio ancora, dovresti impostare il LayoutManager da usare per la JApplet, e poi posizionare il componente.
    codice:
    Container c = getContentPane();
    c.setLayout( new BorderLayout() );
    c.add(finestraGrafica, BorderLayout.CENTER);
    2) Se puoi, evita di caricare le immagini all'interno del metodo paintComponent(). Fallo nel costruttore della classe e valorizza una variabile d'istanza che poi userai nel paintComponent(). Questo velocizza le operazioni poichè il caricamento viene fatto una volta sola e non ad ogni operazione di ridiseno.

    3) Dentro al paintComponent() di una classe non si dovrebbe MAI toccare il graphics di altri componenti: non sai quando questi verranno ridisegnati dal sitema e le tue modifiche, molto probabilmente, verranno sovrascritte. Di fatto, stai ridefinendo il paintComponent() di un pannello, ma non ne effettui alcun ridisegno (non usi il suo Graphics); al contrario, vai a modificare il graphics di altri componenti. Questo è sbagliato.


    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

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2011
    Messaggi
    33
    Se posso vorrei lasciarti il link del problema, che sto trattando anche su stackoverflow

    http://stackoverflow.com/questions/1...japplet-jpanel

    come vedi (se non sto sbagliando) ho già tentato con queste soluzioni, ma senza risultato (ho appena effettuato la correzione 1 che mi hai indicato ma non basta)

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da mkd_
    come vedi (se non sto sbagliando) ho già tentato con queste soluzioni
    Non sono iscritto su StackOverflow... ma da quel che vedo non mi pare che tu abbia corretto quanto riportato nel mio punto 3.
    Quello è il nocciolo della questione: se definisci un componente A, che al suo interno ha un componente B, non è sufficiente ridefinire il metodo paintComponent() di A e da esso modificare il Graphics di B... non funziona così. Anzi, è proprio sbagliato.

    Ciascun componente ha il proprio paintComponent(). Se vuoi modificare il comportamento di un componente, devi ridefinire il suo paintComponent(), non uno qualunque.

    Questo è completamente sbagliato:
    codice:
    paintComponent(Graphics g)
    {
      super.paintComponent(g);
      // Queste righe andrebbero spostate nel costruttore
      Image immagineGrafico=createImage(grafico.pannelloGrafico.getWidth()
                                      ,grafico.pannelloGrafico.getHeight()); 
      Image immagineVolumi=createImage(grafico.pannelloVolumi.getWidth()
                                      ,grafico.pannelloVolumi.getHeight());
    
      // Tutte queste righe non hanno proprio senso:
      // stai cercando di modificare il Graphics di componenti che non sono quello
      // che stai ridefinendo.
      Graphics2D imgGrafico=(Graphics2D)immagineGrafico.getGraphics();
      Graphics2D imgVolumi=(Graphics2D)immagineVolumi.getGraphics();
      grafico.draw(imgGrafico,imgVolumi,mouseX,mouseY);
    
      ((Graphics2D)grafico.pannelloGrafico.getGraphics()).drawImage(immagineGrafico,0,0,this);
      ((Graphics2D)grafico.pannelloVolumi.getGraphics()).drawImage(immagineVolumi,0,0,this);
    }
    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

  5. #5
    Utente di HTML.it
    Registrato dal
    Dec 2011
    Messaggi
    33
    Ti ringrazio per la pazienza
    il codice attuale è il seguente

    paintComponent() del pannello addato alla JApplet

    codice:
      super.paintComponent(g); 
      //Graphics2D schermo=(Graphics2D) g; 
      Image immagineGrafico=createImage(grafico.pannelloGrafico.getWidth()      
                          ,grafico.pannelloGrafico.getHeight()); 
      Image immagineVolumi=createImage(grafico.pannelloVolumi.getWidth() 
                          ,grafico.pannelloVolumi.getHeight()); 
      Graphics2D imgGrafico=(Graphics2D)immagineGrafico.getGraphics(); 
      Graphics2D imgVolumi=(Graphics2D)immagineVolumi.getGraphics(); 
      long start=System.nanoTime(); 
      grafico.draw(imgGrafico,imgVolumi,mouseX,mouseY); 
      long end=System.nanoTime(); 
      grafico.pannelloGrafico.setImg(immagineGrafico);
    e questo il paintComponent() del JPanel addato al JPanel precedente

    codice:
      long start=System.nanoTime(); 
      super.paintComponent(g); 
      Graphics2D schermo=(Graphics2D) g; schermo.drawImage(img,0,0,this); 
      //schermo.drawLine(ChartWindow.mouseX,0,ChartWindow.mouseX,300); 
      long end=System.nanoTime(); 
      //System.out.println("tempo repaintcompChartPanel="+((end-start)/1000000));
    notare che se tolgo tutti i calcoli da grafico.draw il tempo di elaborazione diventa inferiore ai 3 millisecondi. Lasciando attivo solo il disegno di una linea verticale (schermo.drawLine()) che rappresenta il mouse la grafica va sempre a scatti.

    Se non sbaglio dovrebbe essere corretto: il secondo JPanel disegna su se stesso, e il primo JPanel si limita a passare a grafico.draw il graphics di una immagine che verrà poi assegnata al secondo JPanel, che la disegnerà su se stessa

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da mkd_
    Se non sbaglio dovrebbe essere corretto: il secondo JPanel disegna su se stesso, e il primo JPanel si limita a passare a grafico.draw il graphics di una immagine che verrà poi assegnata al secondo JPanel, che la disegnerà su se stessa
    Secondo me non è ancora corretto.
    Mi domando perchè effettui queste operazioni:
    codice:
    //Graphics2D schermo=(Graphics2D) g; 
      Image immagineGrafico=createImage(grafico.pannelloGrafico.getWidth()      
                          ,grafico.pannelloGrafico.getHeight()); 
      Image immagineVolumi=createImage(grafico.pannelloVolumi.getWidth() 
                          ,grafico.pannelloVolumi.getHeight()); 
      Graphics2D imgGrafico=(Graphics2D)immagineGrafico.getGraphics(); 
      Graphics2D imgVolumi=(Graphics2D)immagineVolumi.getGraphics(); 
      long start=System.nanoTime(); 
      grafico.draw(imgGrafico,imgVolumi,mouseX,mouseY); 
      long end=System.nanoTime(); 
      grafico.pannelloGrafico.setImg(immagineGrafico);
    dentro al paintComponent() di un componente che non vuoi modificare.

    Il metodo paintComponent() va ridefinito solo e soltanto se devi ridisegnare il componente stesso. Cioè, solo e soltanto se devi modificare l'oggetto Graphics del componente stesso.

    Tu non lo tocchi nemmeno l'oggetto Graphics, che hai chiamato "schermo".

    Tutto ciò che non riguarda il disegno del componente non ci deve stare dentro al paintComponent(). Ergo... tutte quelle operazioni le dovresti spostare da qualche altra parte, in modo che non coinvolgano il sistema di disegno del componente.

    Non puoi incapsulare "logica di programmazione" dentro ad un metodo che si deve occupare solo e soltanto del disegno di se stesso.

    Io non conosco la logica di funzionamento della tua applet, ma quelle operazioni non vanno fatte là dentro.


    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

  7. #7
    Utente di HTML.it
    Registrato dal
    Dec 2011
    Messaggi
    33
    Grazie mille: in effetti sono li dentro per effettuare il cambiamento suggeritomi la scorsa volta, ma se porta problemi tolgo il paintComponent (che li ormai è inutile). Ti faccio sapere

  8. #8
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    @LeleFT Non ho capito la tua obiezione. Forse non ho letto bene il thread ma se lui ha un JPanel e vuole disegnarci dentro è giusto che ridefinisca il metodo paintComponent, vedi per esempio:
    http://www.java2s.com/Code/JavaAPI/j...tGraphicsg.htm
    Ho letto di fretta il thread eh.

  9. #9
    Utente di HTML.it
    Registrato dal
    Dec 2011
    Messaggi
    33
    Niente. Ho eliminato completamente il paintComponent() del JPanel addato all' applet e trasferito il codice poco prima del repaint, nessun risultato, tutto funziona ma persiste lo sfarfallio.

    Sottolineo ancora che eliminando completamente ogni calcolo, e facendo disegnare al sub-jpanel una linea verticale che si muove con il mouse, tramite

    schermo.drawLine(ChartWindow.mouseX,0,ChartWindow. mouseX,300);

    piazzato nel paintComponent() del sub-pannello lo sfarfallio persiste!

  10. #10
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da c0der
    @LeleFT Non ho capito la tua obiezione. Forse non ho letto bene il thread ma se lui ha un JPanel e vuole disegnarci dentro è giusto che ridefinisca il metodo paintComponent, vedi per esempio:
    http://www.java2s.com/Code/JavaAPI/j...tGraphicsg.htm
    Ho letto di fretta il thread eh.
    E' quello che ho detto anch'io... ma se vuole "disegnare" su altri componenti, deve ridefinire il paintComponent() di questi altri componenti... non può farlo dal paintComponent() di un componente a caso.

    In soldoni, il paintComponent() di un componente A deve occuparsi solo ed esclusivamente di ridisegnare il componente A, non può occuparsi di disegnare altri componenti.

    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

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.