Java 重新绘制会导致组件溢出

Java 重新绘制会导致组件溢出,java,swing,user-interface,jpanel,Java,Swing,User Interface,Jpanel,我希望这次我正确地使用了问句函数。从昨天到现在,我一直被一个问题弄糊涂了。我用谷歌搜索询问我的java老师,但没有解决我的问题 使用repaint时,成形JPanel中的子组件将超出其显示区域。如下图所示 这就是我想要的效果 但当我使用“重新绘制”时,有些事情会发生变化。 一开始这个按钮好像不对劲。 但有时按钮会恢复正常 这是我的密码。我使用重绘是因为我检查的信息告诉我我可以使用它。重新绘制以实现动画效果 import javax.swing.*; import java.awt.*;

我希望这次我正确地使用了问句函数。从昨天到现在,我一直被一个问题弄糊涂了。我用谷歌搜索询问我的java老师,但没有解决我的问题

使用
repaint
时,成形
JPanel
中的子组件将超出其显示区域。如下图所示

这就是我想要的效果

但当我使用“重新绘制”时,有些事情会发生变化。

一开始这个按钮好像不对劲。

但有时按钮会恢复正常

这是我的密码。我使用重绘是因为我检查的信息告诉我我可以使用它。重新绘制以实现动画效果

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;

class GPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        g2d.clip(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), getWidth(), getHeight()));
        g2d.setPaint(Color.BLUE);
        g2d.fillRect(0, 0, getWidth(), getHeight());
    }
}

public class MainComponentOverflow {

    public static void main(String[] args) {
        JFrame frame = new JFrame();

        // This is a panel with a shape
        GPanel panel = new GPanel();

        // This one is the effect I am looking for, the rectangle is displayed in the Panel.
        //panel.add(new Normal());
        // The following two will have problems, the rectangle will be displayed outside the Panel
        //panel.add(new Problem1());
        panel.add(new Problem2());

        //panel.add(new JButton("This will also cause problems, but it may also display properly when I resize the window."));

        frame.add(panel);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

class Normal extends JPanel {

    public Normal() {
        setPreferredSize(new Dimension(500, 500));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
}

class Problem1 extends JPanel implements ActionListener {

    public Problem1() {
        Timer timer = new Timer(16, this);
        timer.start();
        setPreferredSize(new Dimension(500, 500));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
}

class Problem2 extends JPanel implements ActionListener {

    public Problem2() {
        Timer timer = new Timer(16, this);
        timer.start();
        setPreferredSize(new Dimension(500, 500));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        setBackground(new Color((float) Math.random(), (float)Math.random(), (float)Math.random()));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(getBackground());
        g.fillRect(0, 0, getWidth(), getHeight());
    }
}

首先绘制框架时,将在
GPanel
中设置剪辑,然后使用同一剪辑在
Problem1
中绘制子项,因此它将工作

但是,当您重新绘制
Problem1
时,
GPanel
不会首先重新绘制,因此不会设置剪辑,也没有剪辑来限制
Problem1

如果不重新绘制
Problem1
而重新绘制父级,
GPanel
,它将解决您的问题

另一个解决方案是将剪辑也放入
问题1


请注意,当您使用它绘制椭圆时,可以将
RoundRect2D
替换为
Ellipse2D

首先绘制框架时,将在
GPanel
中设置剪辑,然后将在
Problem1
中使用相同的剪辑绘制子项,因此它将起作用

但是,当您重新绘制
Problem1
时,
GPanel
不会首先重新绘制,因此不会设置剪辑,也没有剪辑来限制
Problem1

如果不重新绘制
Problem1
而重新绘制父级,
GPanel
,它将解决您的问题

另一个解决方案是将剪辑也放入
问题1


请注意,当您使用它绘制椭圆时,可以将
RoundRect2D
替换为
Ellipse2D

public class Main{
(叹气…)像
public class MainComponentOverflow这样更具描述性的名称如何{
?我为编写SO代码保留了一个单独的软件包,有很多人希望将他们的代码称为Main!要有创意,要有描述性,让事情对我来说更简单。(请。)我将成为一名有创造力的程序员。谢谢你的建议。
paintComponent
负责绘制组件本身,而不是子组件。子组件由处理。您将希望覆盖这两种方法。有关所有详细信息,请参阅。
public class Main{
(叹气…)像
public class MainComponentOverflow{
这样一个更具描述性的名称如何?我为编写SO代码保留了一个软件包,有很多人想调用他们的代码
Main
!要有创意,要有描述性,让事情对我来说更简单。(请。)我将成为一名有创造力的程序员。感谢您的建议。
paintComponent
负责绘制组件本身,而不是子组件。子组件由处理。您将希望覆盖这两种方法。有关所有详细信息,请参阅。