首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >菜鸟JLayeredPane问题

菜鸟JLayeredPane问题
EN

Stack Overflow用户
提问于 2012-07-18 02:32:52
回答 2查看 7.7K关注 0票数 3

我就是过不了JLayeredPanes的第一步。(参见我的original question of yesterday。我一直在研究JLayeredPane教程和应用编程接口。这些教程与我最终尝试生成的内容略有不同。

回到起点,我采用了甲骨文的JFrame示例,并对其进行了修改,以包括分层窗格。

代码如下:

代码语言:javascript
复制
package components;

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

/* FrameDemo.java requires no other files. */
public class FrameDemo {
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("FrameDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel mainLayer = new JPanel(new BorderLayout());
        mainLayer.setPreferredSize(new Dimension(640, 480));
        frame.setContentPane(mainLayer);
        frame.getLayeredPane().add(mainLayer, JLayeredPane.DEFAULT_LAYER, 0);

        JLabel emptyLabel = new JLabel("LABEL");
        emptyLabel.setPreferredSize(new Dimension(320, 240));
        mainLayer.add(emptyLabel, BorderLayout.NORTH);

        JPanel subLayer = new JPanel(new BorderLayout());
        JLabel subLabel = new JLabel("SUBLABEL");
        subLabel.setPreferredSize(new Dimension( 200, 100));
        subLabel.setBackground(Color.YELLOW);
        subLayer.add(subLabel, BorderLayout.SOUTH);
        subLayer.setVisible(true);
        subLabel.setVisible(true);
        frame.getLayeredPane().add(subLayer, JLayeredPane.PALETTE_LAYER, 0);


        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

为什么不动呢?哇,为什么这个子标签还没出现?它位于比主层更高的层次上。

一种想法是,为什么我要将mainLayer同时添加到内容窗格和分层窗格?如果我不这么做,什么都不会出现。也就是说,通过注释掉这一行,我只得到一个空白的框架。

代码语言:javascript
复制
//        frame.setContentPane(mainLayer);

很明显,我不明白一些事情。但是它是什么呢?

我应该补充说,显然,这个简单的演示可以在没有分层窗格的情况下完成。但我的最终目标是拥有一个可以通过编程打开和关闭的层。但我甚至不能让这个简单的案例起作用。如果我能克服这个困难,我想剩下的就容易多了。

附录:

下面的代码说明了我想要获得的东西,它与TrashGod在下面设置的内容非常相似,并且它是有效的。在整数(-1)层和整数(1)层之间存在具有恒定层(在整数(0)处分层)和浮动层的JLayeredPane,该浮动层最初在整数(-1)处分层,但可通过F7和F8键击来切换,从而允许其浮动在常数层之上或之下。

代码语言:javascript
复制
package components;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;


/* MyLayeredPaneDemo.java requires no other files. */
public class MyLayeredPaneDemo {
    private JFrame frame;
    private JLayeredPane mainPanel;
    private JPanel constantLayer;
    private JPanel floatingLayer;
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private MyLayeredPaneDemo() {}
    private void createAndShowGUI() {
        //Create and set up the window.
        this.frame = new JFrame("MyLayeredPaneDemo");
        this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.frame.setPreferredSize(new Dimension(640, 480));
        mainPanel = new JLayeredPane();
        constantLayer = new JPanel(new BorderLayout(0,0));
        floatingLayer = new JPanel(new BorderLayout(0,0));
//        constantLayer.setPreferredSize();
        constantLayer.setOpaque(true);
        constantLayer.setBackground(Color.BLUE);


        JLabel constantLabel = new JLabel("MAIN LAYER");
        constantLayer.setPreferredSize(new Dimension(640, 480));
        constantLayer.add(constantLabel, BorderLayout.CENTER);

        JLabel subLabel = new JLabel("SUB LAYER");
        floatingLayer.setBackground(Color.YELLOW);
        floatingLayer.add(subLabel, BorderLayout.SOUTH);
        floatingLayer.setOpaque(true);
        floatingLayer.setVisible(true);
        floatingLayer.setVisible(true);
        subLabel.setBackground(Color.YELLOW);

        mainPanel.add(constantLayer, new Integer(0), 0);
        constantLayer.setBounds(0,0,640,480);
        mainPanel.add(floatingLayer, new Integer(-1), 0);
        floatingLayer.setBounds(100, 360, 300, 90 );

        frame.add(mainPanel, BorderLayout.CENTER);

        //Display the window.
        mapKeyToAction(frame.getRootPane(), 
                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
                KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0),
                "Hide Layer", 
                new AbstractAction() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("F7 pressed");
                        mainPanel.setLayer(floatingLayer, new Integer(-1));
                    }       
                }); 
        mapKeyToAction(frame.getRootPane(), 
                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
                KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0),
                "Show Layer", 
                new AbstractAction() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("F8 pressed");
                        mainPanel.setLayer(floatingLayer, new Integer(1));
                    }       
                }); 
        frame.pack();
        frame.setVisible(true);
        frame.getRootPane().setFocusable(true);
        boolean ok = frame.getRootPane().requestFocusInWindow();
        System.out.println("focus ok: " + ok);

    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MyLayeredPaneDemo().createAndShowGUI();
            }
        });
    }

    private static void mapKeyToAction(JComponent component, 
            int whichMap, KeyStroke keystroke,String key, Action action) {
        component.getInputMap(whichMap).put(keystroke, key);
        component.getActionMap().put(key, action);
    }

}

然而,在我的真实案例中,我遇到了困难。两者之间的区别在于,在这里,我的JLayeredPane归框架所有,而在我的实际应用程序中,我希望JLayeredPane归JPanel所有,即框架在包含层次结构中的下一层,其大小由其父节点中的GridBagLoyout设置,因此在调用其构造函数时大小是未知的,这使得调用setBounds()变得困难,这是我需要在JLayeredPane的子节点上执行的操作。

进一步的附录。我知道Oracle教程提到了一个case where Layouts rather than absolute positioning is used with a JLayeredPane。这种情况和我的情况的不同之处在于,在我的情况下,层在不同层上占用相同的水平空间,而在这种情况下,不同层上的组件占用不同的水平空间。这几乎就像我们需要一个3D布局管理器!

EN

回答 2

Stack Overflow用户

发布于 2012-07-18 09:49:59

“默认情况下,分层窗格没有布局管理器。”-

附录:我需要避免使用Frame的分层窗格,而是在窗口中添加分层窗格。

是的,是JRootPane的一个实例,其中包含一个JLayeredPane。特别是,“layered窗格包含菜单栏和内容窗格,并支持对其他组件进行Z排序。”

代码语言:javascript
复制
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FrameDemo {

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("FrameDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLayeredPane mainLayer = new JLayeredPane();
        frame.add(mainLayer, BorderLayout.CENTER);

        JLabel label = new JLabel("LABEL", JLabel.CENTER);
        label.setBounds(100, 100, 200, 100);
        label.setOpaque(true);
        label.setBackground(Color.cyan);
        mainLayer.add(label, 1);

        JPanel subLayer = new JPanel(new BorderLayout());
        JLabel subLabel = new JLabel("SUBLABEL", JLabel.CENTER);
        subLabel.setBounds(20, 20, 200, 100);
        subLabel.setOpaque(true);
        subLabel.setBackground(Color.yellow);
        subLayer.add(subLabel, BorderLayout.SOUTH);
        mainLayer.add(subLabel, 2);

        frame.pack();
        frame.setSize(320, 240);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
票数 4
EN

Stack Overflow用户

发布于 2012-07-20 10:06:17

多亏了垃圾神,我想到的解决方案是实现ComponentListener并捕获组件调整大小事件。在这一点上,您可以获得容器的实际边界,并使用它来设置JPanels层的实际边界,这些边界始终与包含它们的组件的边界保持一定的关系。它起作用了。

我相信“垃圾神”的解决方案也能行得通,但我还没有试过。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11528677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档