Java JLayeredPane未绘制

Java JLayeredPane未绘制,java,jframe,jpanel,paint,jlayeredpane,Java,Jframe,Jpanel,Paint,Jlayeredpane,你好 希望这是一个快速解决问题。我正在编写一个在JFrame中使用JPanels和JLayeredPane的应用程序。在应用程序的初始启动时,其中一个面板不会显示,直到我的鼠标移动到面板应该所在的区域。我甚至调用了validate和repait方法,但我仍然能够同时显示这两个面板。有什么建议吗?多谢各位 这是我的JFrame类(它有main方法) 这是我的一个面板类 import javax.swing.JButton; import javax.swing.JPanel; public cl

你好

希望这是一个快速解决问题。我正在编写一个在JFrame中使用JPanels和JLayeredPane的应用程序。在应用程序的初始启动时,其中一个面板不会显示,直到我的鼠标移动到面板应该所在的区域。我甚至调用了validate和repait方法,但我仍然能够同时显示这两个面板。有什么建议吗?多谢各位

这是我的JFrame类(它有main方法)

这是我的一个面板类

import javax.swing.JButton;
import javax.swing.JPanel;

public class Mypanel extends JPanel
{
    public JButton button;

    public Mypanel()
    {
        this.setLayout(null);
        this.setBounds(0, 0, 500, 500);
        JButton b = new JButton("Hello");
        b.setBounds(20,20,300,300);
        this.add(b);
    }
}
import javax.swing.JButton;
import javax.swing.JPanel;


public class Mypanel2 extends JPanel
{
    public JButton button;

    public Mypanel2()
    {
        this.setLayout(null);
        this.setBounds(0, 0, 500, 500);
        JButton b = new JButton("SUP");
        b.setBounds(20,10,200,200);
        this.add(b);
        this.repaint();
        this.validate();
        this.repaint();
    }
}
最后是我的最后一堂小组课

import javax.swing.JButton;
import javax.swing.JPanel;

public class Mypanel extends JPanel
{
    public JButton button;

    public Mypanel()
    {
        this.setLayout(null);
        this.setBounds(0, 0, 500, 500);
        JButton b = new JButton("Hello");
        b.setBounds(20,20,300,300);
        this.add(b);
    }
}
import javax.swing.JButton;
import javax.swing.JPanel;


public class Mypanel2 extends JPanel
{
    public JButton button;

    public Mypanel2()
    {
        this.setLayout(null);
        this.setBounds(0, 0, 500, 500);
        JButton b = new JButton("SUP");
        b.setBounds(20,10,200,200);
        this.add(b);
        this.repaint();
        this.validate();
        this.repaint();
    }
}

首先,在一个有效的程序中,只有组件重新绘制自身。如果在某个时候,您发现从控制器代码中调用
c.repaint()
可以解决一些问题,那么您就忽略了swing框架核心的基本契约。这从来都不是个好主意。因此,删除所有这些
repaint
validate
调用是一个好的开始。下一个重要的事情是了解轻量级swing组件如何为其孩子上漆。有两种模式:优化和未优化。第一种方法仅适用于容器中兄弟节点不重叠的情况。如果它们这样做了,并且启用了“优化绘制”,那么当这些组件重新绘制它们自己时(比如当您将鼠标指针悬停在它们上面时),您将获得各种奇怪的行为。所有轻量级组件都可以通过
setComponentZOrder()
处理重叠的子级。JLayeredPane只引入了层的概念,作为以更灵活的方式控制zorder的一种手段。它试图聪明地选择什么模式来画它的孩子,但不幸的是,这其中有微妙之处。因此,此代码将执行您需要的操作:

Mypanel p1 = new Mypanel();
Mypanel2 p2 = new Mypanel2();

getLayeredPane().setLayer(p1,0);
getLayeredPane().setLayer(p2,1);

getLayeredPane().add(p1);
getLayeredPane().add(p2);
而这不会:

Mypanel p1 = new Mypanel();
Mypanel2 p2 = new Mypanel2();

getLayeredPane().add(p1);
getLayeredPane().add(p2);

getLayeredPane().setLayer(p1,0);
getLayeredPane().setLayer(p2,1);
诀窍是在将子对象添加到容器之前调用
setLayer
,以便JLayeredPane关闭优化的绘制


顺便说一句,我忍不住想知道为什么
JLayeredPane
?如果您需要以编程方式在不同布局之间切换,那么JTabbedPane可能是您的答案

首先,在有效的程序中,只有JComponent重新绘制自身。如果在某个时候,您发现从控制器代码中调用
c.repaint()
可以解决一些问题,那么您就忽略了swing框架核心的基本契约。这从来都不是个好主意。因此,删除所有这些
repaint
validate
调用是一个好的开始。下一个重要的事情是了解轻量级swing组件如何为其孩子上漆。有两种模式:优化和未优化。第一种方法仅适用于容器中兄弟节点不重叠的情况。如果它们这样做了,并且启用了“优化绘制”,那么当这些组件重新绘制它们自己时(比如当您将鼠标指针悬停在它们上面时),您将获得各种奇怪的行为。所有轻量级组件都可以通过
setComponentZOrder()
处理重叠的子级。JLayeredPane只引入了层的概念,作为以更灵活的方式控制zorder的一种手段。它试图聪明地选择什么模式来画它的孩子,但不幸的是,这其中有微妙之处。因此,此代码将执行您需要的操作:

Mypanel p1 = new Mypanel();
Mypanel2 p2 = new Mypanel2();

getLayeredPane().setLayer(p1,0);
getLayeredPane().setLayer(p2,1);

getLayeredPane().add(p1);
getLayeredPane().add(p2);
JLayeredPane lp = new JLayeredPane();
JPanel d = new JPanel();
d.setVisible(true);
d.setBounds(10, 10, 556, 386);
lp.add(d, new Integer(0), 0);
而这不会:

Mypanel p1 = new Mypanel();
Mypanel2 p2 = new Mypanel2();

getLayeredPane().add(p1);
getLayeredPane().add(p2);

getLayeredPane().setLayer(p1,0);
getLayeredPane().setLayer(p2,1);
诀窍是在将子对象添加到容器之前调用
setLayer
,以便JLayeredPane关闭优化的绘制


顺便说一句,我忍不住想知道为什么
JLayeredPane
?如果您需要以编程方式在不同的布局之间切换,也许JTabbedPane就是您的答案

嗨,安德鲁!谢谢你的回复。这就是我真正想做的。。。我有一个缓冲图像的背景,这将是一个2D游戏。我不想编写自己的按钮和文本字段类,所以我打算在包含我的图像的层的顶部创建一个层。您是否有更好的方法来执行此操作?在这种情况下,您可能需要使用
GlassPane
,而不是
JLayeredPane
!有很多方法可以满足你的需要。我首先创建自己的
JPanel
子类,将其不透明属性设置为true,然后覆盖其
paintComponent
以绘制缓冲图像。仅仅为了绘制图像,不需要使用JLabel或JButton。您可以通过add()/remove()方法添加/删除其他swing组件,如JTextField或JButton。简单!顺便说一句,将所有鼠标操作/绘制封装在单个组件中会有所帮助。根据我的经验,坚持MVC原则总是值得的。特别是在桌面/游戏开发方面。嗨,安德鲁!谢谢你的回复。这就是我真正想做的。。。我有一个缓冲图像的背景,这将是一个2D游戏。我不想编写自己的按钮和文本字段类,所以我打算在包含我的图像的层的顶部创建一个层。您是否有更好的方法来执行此操作?在这种情况下,您可能需要使用
GlassPane
,而不是
JLayeredPane
!有很多方法可以满足你的需要。我首先创建自己的
JPanel
子类,将其不透明属性设置为true,然后覆盖其
paintComponent
以绘制缓冲图像。仅仅为了绘制图像,不需要使用JLabel或JButton。您可以通过add()/remove()方法添加/删除其他swing组件,如JTextField或JButton。简单!顺便说一句,将所有鼠标操作/绘制封装在单个组件中会有所帮助。根据我的经验,坚持MVC原则总是值得的。特别是在桌面/游戏开发中。欢迎使用Stack Overflow,您可以在代码中提供一些解释吗?欢迎使用Stack Overflow,您可以在代码中提供一些解释吗?
JLayeredPane lp = new JLayeredPane();
JPanel d = new JPanel();
d.setVisible(true);
d.setBounds(10, 10, 556, 386);
lp.add(d, new Integer(0), 0);