views:

147

answers:

2

I have 2 JPanels in a JTabbedPane and when update(g) is called on a panel inside the first panel (Its an animation) even if the second panel is the selected panel(i.e the one you can see) the updated panel appears on the screen. Why is this and how can i circumvent this behaviour?

+4  A: 

The update() method of JComponent "doesn't clear the background," so you may need to do that explicitly. Typical examples of JTabbedPane don't usually require using update(). Perhaps an sscce showing your usage might help.

Addendum 1: It's not clear why you are calling update(). Below is a simple animation that does not exhibit the anomaly.

Addendum 2: See Painting in AWT and Swing: paint() vs. update(). You may want to use repaint() in actionPerformed() instead.

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class JTabbedTest {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            //@Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JTabbedPane jtp = new JTabbedPane();
                jtp.setPreferredSize(new Dimension(320, 200));
                jtp.addTab("Reds", new ColorPanel(Color.RED));
                jtp.addTab("Greens", new ColorPanel(Color.GREEN));
                jtp.addTab("Blues", new ColorPanel(Color.BLUE));

                f.add(jtp, BorderLayout.CENTER);
                f.pack();
                f.setVisible(true);
            }
        });
    }

    private static class ColorPanel extends JPanel implements ActionListener {

        private final Random rnd = new Random();
        private final Timer timer = new Timer(1000, this);
        private Color color;
        private int mask;
        private JLabel label = new JLabel("Stackoverflow!");

        public ColorPanel(Color color) {
            super(true);
            this.color = color;
            this.mask = color.getRGB();
            this.setBackground(color);
            label.setForeground(color);
            this.add(label);
            timer.start();
        }

        //@Override
        public void actionPerformed(ActionEvent e) {
            color = new Color(rnd.nextInt() & mask);
            this.setBackground(color);
        }
    }
}
trashgod
I'm not calling update on the JTabbedPane, it is called on a component inside one of the panels in the JTabbedPane, the problem is that the component is always painted to the screen even if the panel in which is resides isn't the selected panel.
denis
adding an update() to your ActionPerformed() creates my problem.
denis
See the added link above.
trashgod
+2  A: 

when update(g) is called on a panel inside the first panel (Its an animation)

Overriding the update(...) method is an old AWT trick and should never be used with Swing.

Read the section from the Swing tutorial on Custom Painting for the proper way to do this. And for animation read up on "How to Use Swing Timer" found in the tutorial as well.

camickr
+1 Override `update()`? Who knew!
trashgod
how does overriding or even calling update() cause a problem like mine?
denis
IIUC, it mixes AWT and Swing.
trashgod
I can't answer why calling update() is causing a problem in your situation because your question contains no code or specific information. All I know is that people blindly copy code they find on the net, not realizing that painting in AWT and Swing work differently and you can't just mix and match code. Read the link provided by trashgod for a better understanding of painting and don't forget the tutorials I pointed you to as well.
camickr