是什么决定了组件在 Java 中的可见性?

What determines component visibility in Java?

我正在编写一个 Java GUI 程序,它使用一个 JFrame 对象和几个 JPanel 对象。 JPanel 对象使用 paint() 和 repaint() 方法,一些 JPanel 对象具有 JLabel 和 JButton。当我 运行 程序时,这些不同组件中的一些组件并不像我希望的那样可见,即似乎有些组件隐藏了其他组件。

什么决定程序在运行时哪些组件可见?是取决于组件添加到顶层容器的顺序,还是取决于每个对象的paint()方法的调用顺序?可以覆盖此默认可见性吗?

编辑:我应该补充一点,一些 JPanel(及其组件)相互重叠。

编辑: 这是一个示例程序。什么决定了哪些组件在屏幕上可见?例如,为什么 Button1 可见而 Button2 不可见?

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

public class Test1 extends JFrame {

  public Test1() {
    setLayout(null);
    setSize(500, 700);
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    add(new Test2());
    setVisible(true);
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        new Test1();
      }
    });
  }
}

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

public class Test2 extends JPanel {

  public Test2() {
    setBounds(0, 0, 300, 500);
    setLayout(null);
    add(new Test3());
    add(new Test4());
    setVisible(true);
  }

  public void paint(Graphics g) {
    g.drawRect(0, 0, 250, 450);
  }
}

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

public class Test3 extends JPanel {

  public Test3() {
    setBounds(0, 0, 300, 300);
    setVisible(true);
  }

  public void paint(Graphics g) {
    g.fillRect(40, 50, 200, 150);
  }
}

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

public class Test4 extends JPanel {

  public JLabel label1 = new JLabel("Label1");
  public JLabel label2 = new JLabel("Label2");

  public JButton button1 = new JButton("Button1");
  public JButton button2 = new JButton("Button2");

  public Test4() {
    setBounds(0, 300, 300, 200);

    add(label1);
    add(label2);
    add(button1);
    add(button2);

    setVisible(true);
  }
}

I should add that some JPanels (and their components) overlap each other.

ZOrder 控制绘制组件的顺序。优先绘制 ZOrder 较高的组件。

Does it depend on the order in which the components are added to the top-level container

是的,ZOrder 被指定为一个组件被添加到容器中,所以最后添加的组件将首先被绘制。

您可以使用 Container class 的 setComponentZOrder(...) 方法手动更改 ZOrder(从而更改绘制顺序)。例如,如果您拖动一个组件并希望它在顶部绘制,您可以将其 ZOrder 设置为 0。

您可能想查看 Overlap Layout。它允许您控制组件在重叠时的显示方式(尽管它确实使所有组件大小相同)

Here is an example program.

你永远不应该写这样的应用程序,因为你会遇到各种各样的问题:

  1. 不要使用空布局管理器。
  2. 不要覆盖 paint()。自定义绘画是通过覆盖 paintComponent() 并确保调用 super.paintComponent(...) 来完成的。
  3. 不要一个接一个地堆叠面板。 JPanel 是不透明的,因此在另一个之上添加组件会隐藏下面的组件。

why is Button1 visible when Button2 is not?

Button1 已绘制,因为它有焦点。如果您将鼠标移到 button2 旁边,它也会被绘制,因为它响应 mouseOver 事件。

如果调整框架的大小,两个按钮都会消失,因为面板将根据 ZOrder 重新绘制。

我真的不知道你想用那个代码做什么。我只能说不要这样做。使用布局管理器。