Java - repaint(x, y, w, h) doesn't call paintComponent? (with SSCCE)

独自空忆成欢 提交于 2019-12-02 00:09:30

问题


I asked this before, but only theoretically, without an SSCCE. Now, I've created one, and the problem persists. I'd like to know why paintComponent is not called on repaint(x, y, w, h), but is called on repaint().

Two classes:

SANDBOX

import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JFrame;

public class Sandbox {
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setMinimumSize(new Dimension(800, 600));
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new FlowLayout());

        // Add label
        f.getContentPane().add(new TLabel());

        f.setVisible(true);
    }
}

and TLabel (with a little styling):

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;

@SuppressWarnings("serial")
public class TLabel extends JLabel {
    public TLabel() {
    super("TEST LABEL, NON-STATIC");
    this.setHorizontalAlignment(SwingConstants.CENTER);
    TLabel.this.setPreferredSize(new Dimension(200, 50));
    TLabel.this.setMaximumSize(new Dimension(200, 50));
    TLabel.this.setMinimumSize(new Dimension(200, 50));

    TLabel.this.setOpaque(true);
    TLabel.this.setBackground(Color.cyan.darker().darker());
    TLabel.this.setForeground(Color.white);
    TLabel.this.setBorder(new LineBorder(Color.orange, 2));

    this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                // EXPECTED BEHAVIOR HERE: This line will call paint and paintComponent.
                //repaint();

                // PROBLEM HERE: This line will not call paint or paintComponent.
                repaint(TLabel.this.getBounds());
        }
    });
    }

    @Override
    public void paint(Graphics g) {
    // Note: This is called once when the label is realised.
    // Note: This is called when the mouse enters the frame.
    System.out.println("PAINT.");
    super.paint(g);
    }

    @Override
    public void paintComponent(Graphics g) {
    // Note: This is called once when the label is realised.
    // Note: This is called when the mouse enters the frame.
    System.out.println("REPAINT.");
    super.paintComponent(g);
    }
}

回答1:


You're calling this

repaint(TLabel.this.getBounds());

inside of the TLabel object. So repaint will try to paint a rectangle located relative to itself at the Bounds location, but getBounds() returns a rectangle located relative to this components containing object's location while repaint expects bounds relative to the component itself. So you're trying to paint a rectangle that has the width and height of your JLabel but which is located at x = 292 and y = 5 relative to the JLabel, when instead you want x and y to both be 0. In essence you're trying to draw way outside of this component.

Instead try this:

        //!! repaint(TLabel.this.getBounds());
        Dimension d = TLabel.this.getSize();
        repaint(new Rectangle(0, 0, d.width, d.height));


来源:https://stackoverflow.com/questions/9288127/java-repaintx-y-w-h-doesnt-call-paintcomponent-with-sscce

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!