问题描述
之前我问过这个,但理论上只是在没有SSCCE的情况下。现在,我创建了一个,问题仍然存在。我想知道为什么 paintComponent
未在重绘(x,y,w,h)
上调用,但是在上调用repaint()
。
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()
.
两个类:
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);
}
}
和 TLabel (与一点造型):
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);
}
}
推荐答案
你'调用此
repaint(TLabel.this.getBounds());
在TLabel对象内部。因此重绘将尝试在Bounds位置绘制相对于其自身的矩形,但getBounds()返回相对于此组件包含对象位置的矩形,而重绘期望相对于组件本身的边界。因此,您尝试绘制一个矩形,该矩形具有JLabel的宽度和高度,但相对于JLabel 位于x = 292和y = 5 时相反,你希望x和y都为0.本质上你试图在这个组件之外绘制方式。
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.
请试试这个:
//!! repaint(TLabel.this.getBounds());
Dimension d = TLabel.this.getSize();
repaint(new Rectangle(0, 0, d.width, d.height));
这篇关于Java - 重绘(x,y,w,h)不调用paintComponent? (与SSCCE)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!