user3466639
user3466639

Reputation: 13

Parent Panel not repainting correctly

I have a panel which contains custom components that have been added to it. It paints correctly except when the components (which have their own mouselisteners) are being dragged it starts to paint weirdly.

Interestingly if I slightly re-size the parent panel it will now paint as intended. I know that the parent panel is being repainted through

 super.paintComponent(g);

and a print statement inside the panels

paintComponent(Graphics g):

method. I tried revalidating when the component is dragged around (as the component is having its bounds re-set) it becomes invalidated. Still I am having no success and was wondering if anyone could help.

Is there some place where i am not repainting correctly that might be causing this behavior?

Also as an addendum I have a mouse listener on both the panel and its components, is there a way so that when a component is clicked the panel mouse listener also responds (beyond going back up to the parent class from the component)

Here is a working example of the issue I am having

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;

public class testHome {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    testHome window = new testHome();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public testHome() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new myPanel();
        frame.getContentPane().add(panel, BorderLayout.CENTER);
    }
}

class myPanel extends JPanel {

    MyComponent comp;

    public myPanel() {
        super(null);
        comp = new MyComponent(5, 5);
        this.add(comp);
        revalidate();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        Line2D.Double line = new Line2D.Double(10, 10, comp.getX(), comp.getY());
        System.out.println(comp.getX() + " " + comp.getY());
        g2d.draw(line);
    }
}

class MyComponent extends JComponent implements MouseListener, MouseMotionListener {

    int x;
    int y;

    int mx;
    int my;

    public MyComponent(int x, int y) {
        this.setVisible(true);
        this.setBounds(x, y, 15, 15);
        this.x = x;
        this.y = y;
        addMouseMotionListener(this);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.black);
        g2d.fillRect(this.x, this.y, 15, 15);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // TODO Auto-generated method stub
        System.out.println("dragging");
        int dx = e.getX() - mx;
        int dy = e.getY() - my;
        this.setBounds(this.getX() + dx, this.getY() + dy, 15, 15);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        mx = e.getX();
        my = e.getY();
    }

    @Override
    public void mouseMoved(MouseEvent e) {}

    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

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

Upvotes: 0

Views: 704

Answers (1)

kiheru
kiheru

Reputation: 6618

The parent panel does not actually get automatically repainted completely. paintComponent() is called, but if you check the clipping, for example by:

System.out.println(g.getClipBounds());

you'll see that only the area below the smaller component is painted. (The component is not opaque, so the parent component needs to paint the area below it). You need to call repaint() explicitly for the parent panel:

getParent().repaint();

(Or using the repaint() variants that specify the region, if the parent component is expensive to draw and can optimize partial draws).

Upvotes: 2

Related Questions