Java 在从其他源重新绘制父级之前,不会绘制添加的零部件

Java 在从其他源重新绘制父级之前,不会绘制添加的零部件,java,swing,java-8,Java,Swing,Java 8,当我在任何深度的组件树中修改组件时,修改通常会立即自动显示,而无需我为此采取任何行动 当修改是添加新的子项时,情况并非如此。 此外,如果我想使用任何适当的方法(据我对API的理解)强制重新绘制,这也没有实际效果 只有在对现有树(包括添加但仍然不可见的组件)进行新修改时,添加的子级才会出现 下面是一个示例,它将渲染一个底部带有“添加”按钮的黑色窗口。单击按钮将无效。调整窗口大小或最小化窗口将导致出现与按钮之前按下时一样多的白色“XX”字符串 当然,每当按下按钮时,我非常希望添加的内容立即一个接一个

当我在任何深度的组件树中修改组件时,修改通常会立即自动显示,而无需我为此采取任何行动

当修改是添加新的子项时,情况并非如此。
此外,如果我想使用任何适当的方法(据我对API的理解)强制重新绘制,这也没有实际效果

只有在对现有树(包括添加但仍然不可见的组件)进行新修改时,添加的子级才会出现

下面是一个示例,它将渲染一个底部带有“添加”按钮的黑色窗口。单击按钮将无效。调整窗口大小或最小化窗口将导致出现与按钮之前按下时一样多的白色“XX”字符串

当然,每当按下按钮时,我非常希望添加的内容立即一个接一个地出现

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Applikation
{
  public static void main(String[] argumente)
  {
    Box dummy     = new Box(BoxLayout.Y_AXIS);
    JFrame window = new JFrame();
    JPanel panel  = new JPanel();

    panel.setBackground(Color.black);
    window.add(dummy);
    dummy.add(panel);

    JButton button = new JButton("Add");
    button.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e)
    {
      JLabel white = new JLabel("XX");
      white.setBackground(Color.white);
      white.setForeground(Color.white);
      panel.add(white);   // only visible after resizing window or switching focus to another program and back
      panel.invalidate(); // does nothing
      panel.repaint();    // does nothing
      panel.repaint(200); // does nothing
    } });

    dummy.add(button);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);
  }
}
我错过了什么


请注意,这本质上是的一个副本,但正如我在示例代码中看到的,它的答案都不适用:它们在经验上不起作用。

1。(添加所有JComponent后)重新验证+重新绘制(所有JComponents填充ContentPane中的当前矩形)或打包(JFrames bound根据JComponents PreferedSize计算而成),2。默认情况下,从Java6@mKorbel:“pack”要求在组件树的该叶中知道顶级容器。不好的。“重新验证+重新绘制”在我的生活代码中出人意料地起作用,但在我发布的示例代码中却不起作用。看起来答案比这要复杂一点。那段代码不会如图所示编译,所以显然不是你说的代码不起作用。如果
JPanel panel=newjpanel(),它将编译改为
final JPanel panel=new JPanel()但这不是重点。@AndrewThompson:那么您的Java安装似乎有问题。我只是将这个页面中的代码复制粘贴到一个新的文本文件中,并使用jdk1.8.0_66中的javac在没有任何参数的情况下对其进行编译。它不仅进行编译,而且其行为与我描述的完全相同。
revalidate
+
repaint
在这个示例中起作用。但是,由于要使整个树无效(
add
隐式地执行此操作,因此手动调用
invalidate
是过时的),正确的方法是在最顶端的组件上调用
validate()
revalidate()
。注意。(添加所有JComponent后)重新验证+重新绘制(所有JComponents填充ContentPane中的当前矩形)或打包(JFrames bound根据JComponents PreferedSize计算而成),2。默认情况下,从Java6@mKorbel:“pack”要求在组件树的该叶中知道顶级容器。不好的。“重新验证+重新绘制”在我的生活代码中出人意料地起作用,但在我发布的示例代码中却不起作用。看起来答案比这要复杂一点。那段代码不会如图所示编译,所以显然不是你说的代码不起作用。如果
JPanel panel=newjpanel(),它将编译改为
final JPanel panel=new JPanel()但这不是重点。@AndrewThompson:那么您的Java安装似乎有问题。我只是将这个页面中的代码复制粘贴到一个新的文本文件中,并使用jdk1.8.0_66中的javac在没有任何参数的情况下对其进行编译。它不仅进行编译,而且其行为与我描述的完全相同。
revalidate
+
repaint
在这个示例中起作用。但是,由于要使整个树无效(
add
隐式地执行此操作,因此手动调用
invalidate
是过时的),正确的方法是在最顶端的组件上调用
validate()
revalidate()
。注意…