Algum Swing guru aqui?

Estou tentando descobrir porque um JComponent nunca chama um paintComponent().

package com.smartjava.lohis.gui.video;

import java.awt.*;
import javax.swing.*;

public class VideoList extends JComponent {
    
    private static final boolean DEBUG = true;
    
    private ListModel model;
    
    private JScrollPane scroll;
    private JPanel panel;
    
    public VideoList() {
        this(null);
    }
    
    public VideoList(ListModel model) {
        super();
        this.model = model;
        
        panel = new JPanel();
        panel.setLayout(new FlowLayout());
        
        scroll = new JScrollPane(panel);
        
        setLayout(new BorderLayout());
        add(BorderLayout.CENTER, scroll);
    }
    
    public void setModel(ListModel model) {
        this.model = model;
    }
    
    public ListModel getModel() {
        return model;
    }
    
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        panel.removeAll();
        if (model != null) {
            synchronized(model) {
                for(int i=0;i<model.getSize();i++) {
                    panel.add((Component) model.getElementAt(i));
                }
            }
        }
        scroll.revalidate();
    }
    
    // sem isso daqui paintComponent não é nunca chamado !!!!
    public void paint(Graphics g) {
        super.paint(g);
        paintComponent(g);
    }
}

>

Tente usar o método repaint().

Que erro que ele dá hein ???

Mesmo chamando repaint() o JComponent ignora o paintComponent, por algum motivo que eu desconheço. O único jeito foi dar um override no paint() e chamar o paintComponent na mão. Mas isso não é uma boa prática, segundo a própria Sun. Alguém consegue entender isso ??? Por que o puto do JComponent não gosta de chamar o paintComponent !!!???

Executem o código abaixo que vcs vão entender exatamente o que eu quero e o problema:


import java.awt.*;
import javax.swing.*;

public class VideoList extends JComponent {
    
    private static final boolean DEBUG = true;
    
    private ListModel model;
    
    private JScrollPane scroll;
    private JPanel panel;
    
    public VideoList() {
        this(null);
    }
    
    public VideoList(ListModel model) {
        super();
        this.model = model;
        
        panel = new JPanel();
        panel.setLayout(new FlowLayout());
        
        scroll = new JScrollPane(panel);
        
        setLayout(new BorderLayout());
        add(BorderLayout.CENTER, scroll);
    }
    
    public void setModel(ListModel model) {
        this.model = model;
    }
    
    public ListModel getModel() {
        return model;
    }
    
    protected void paintComponent(Graphics g) {
        if (DEBUG) System.out.println("PAINTCOMPONENT !!!");
        super.paintComponent(g);
        panel.removeAll();
        if (model != null) {
            synchronized(model) {
                for(int i=0;i<model.getSize();i++) {
                    panel.add((Component) model.getElementAt(i));
                }
            }
        }
        scroll.revalidate();
    }
    
    // COMENTEI PARA VCS ENTENDEREM QUE SEM ISSO NAO FUNCIONA !!!
    /*
    public void paint(Graphics g) {
        if (DEBUG) System.out.println("PAINT !!!");
        super.paint(g);
        paintComponent(g);
    }
    */
    
    public static void main(String [] args) throws Exception {
        JFrame frame = new JFrame("Testando VideoList");
        
        VideoList vl = new VideoList(new DefaultListModel());
        DefaultListModel model = (DefaultListModel) vl.getModel();
        
        frame.setContentPane(vl);
        frame.setSize(200, 200);
        frame.setVisible(true);
        
        Thread.sleep(5000);
        
        JLabel label = new JLabel("Sergio");
        model.addElement(label);
        vl.repaint();
        System.out.println("FOI !!!");
    }
        
}
        

E aí Sérgio, blz!!

Seguinte, o seu problema está no seguinte:

        add(BorderLayout.CENTER, scroll);

Com isso o seu scroll ocupa toda a área de pintura do seu componente…
Dessa maneira o swing sabe que não precisa chamar paintComponent e chama apenas o paintChidren…

Vc até pode testar trocando o Layout para Flow ao invés do Border…

Espero ter ajudado…

Fallow

Ajudou pra caramba !!! Valeu !!!

Como é que vc sabia disso !!!??? :-o

Então tudo que eu fiz foi dar um override no paintChildren que tudo funcionou as mil maravilhas, sem ter que dar um override no paint().

O Swing é cheio de pegadinhas…

Outra: Chamar repaint() numa scroll é inútil. Pra mim só funcionou o tal do revalidate(), isto é, quando eu adiciono um elemento na minha VideoList, tenho que chamar revalidate no scroll e não repaint. (Veja isso no código acima!)

Vc sabia dessa também, TedLoprao ??? :slight_smile:

O loprão é sinistro no swing…jah me ajudou algumas vezes com problemas nele… :smiley:
Agora,esses bugs q por vezes descobrimos no swing é q mata…uma vez perdi3 dias para arrumar uma tela para depois descobri q era um Bug do swing lah no site da Sun… :roll: