【问题标题】:JLayeredPane not drawingJLayeredPane 不绘图
【发布时间】:2012-06-25 20:09:35
【问题描述】:

早安,

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

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

import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;


public class Application extends JFrame
{
    public Application()
    {   
        this.setSize(500,500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        JLayeredPane lp = new JLayeredPane();
        lp.setBounds(0,0,500,500);
        this.setLayeredPane(lp);

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

        this.getLayeredPane().add(p1,0);
        this.getLayeredPane().add(p2,1);

        this.validate();
        this.repaint();
        this.validate();
    }


    public static void main(String[] args)
    {
        Application app = new Application();

    }
}

这是我的面板类之一

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();
    }
}

【问题讨论】:

    标签: java jframe jpanel paint jlayeredpane


    【解决方案1】:

    首先,在一个有效的程序中,只有JComponent 会重新绘制自己。如果在某些时候你发现从你的控制器代码中调用c.repaint() 可以解决一些问题,那么你已经忽略了作为 Swing 框架核心的基本合约。这从来都不是一个好主意。所以删除所有repaintvalidate 调用是一个好的开始。下一个重要的事情是了解轻量级秋千组件是如何为他们的孩子绘画的。有两种模式:优化和未优化。第一个仅适用于兄弟姐妹在容器中不相互重叠的情况。如果他们这样做了并且优化了绘制,那么当这些组件重新绘制自己时(例如当您将鼠标指针悬停在它们上方时),您将获得各种奇怪的行为。所有轻量级组件都可以通过 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 是您的答案

    【讨论】:

    • 你好安德鲁!感谢您的大力响应。所以这就是我真正想要做的......我在背景中有一个缓冲图像,这将是一个 2D 游戏。我不想编写自己的按钮和文本字段类,因此我将在包含我的图像的图层之上添加一个图层。你有更好的想法吗?
    • 在这种情况下,您可能需要使用GlassPane 而不是JLayeredPanedocs.oracle.com/javase/tutorial/uiswing/components/…
    • 有很多方法可以满足您的需求。我将首先创建自己的JPanel 子类,将其 opaque 属性设置为 true,然后覆盖其paintComponent 以绘制缓冲图像。不需要 JLabel 或 JButton 来绘制图像。您可以通过 add()/ remove() 方法添加/删除其他摆动组件,例如 JTextField 或 JButton。简单的!顺便说一句,它有助于将所有鼠标处理/绘画封装在一个组件中。根据我的经验,坚持 MVC 原则总是有回报的。尤其是桌面/游戏开发。
    【解决方案2】:
    JLayeredPane lp = new JLayeredPane();
    JPanel d = new JPanel();
    d.setVisible(true);
    d.setBounds(10, 10, 556, 386);
    lp.add(d, new Integer(0), 0);
    

    【讨论】:

    • 欢迎来到 Stack Overflow,您能否在代码中提供一些解释?
    猜你喜欢
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 2011-10-12
    • 2011-11-05
    • 2013-09-16
    • 2012-09-03
    相关资源
    最近更新 更多