叠加面板(在另一个上面)

时间:2012-01-09 16:52:35

标签: java swing

我正在学习如何使用Swing,发现自己很难完成任务。

我想要实现的目标:我希望左侧有一个面板(称之为菜单面板)(比方说100px宽度)和第二个面板(称之为内容面板),这将占用剩下的可用位置。

在菜单面板中有3个按钮。当我按下它们时,在菜单面板的右侧(在内容面板上)应出现第二个菜单面板(子菜单)(它应该从按下的按钮中间开始)。

可能很难理解,所以我创建了简单的草稿:

enter image description here

我尝试过JLayeredPane,但是调整窗口大小时出现问题(分层窗格中的元素没有调整大小)。

4 个答案:

答案 0 :(得分:4)

JLayeredPane错过LayoutManager的实施,您必须手动setPreferredSizesetBounds调整/放置JComponents

有一种可行的解决方法,您可以将ComponentListener添加到JFrame,然后在componentResized(ComponentEvent e)上,您可以将JComponent(s)调整大小/替换为所需的Bounds < / p>

例如

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

public class LayeredPaneWithOverlap {

    private JTextArea textArea = new JTextArea(2, 10);
    private JPanel textPanel = new JPanel(new BorderLayout());
    private JTable table = new JTable(30, 5);
    private JScrollPane scroll = new JScrollPane(table);
    private JLayeredPane layer = new JLayeredPane();
    private JFrame frame = new JFrame("Frame with resiziable JLayeredPane");

    public void makeUI() {
        textArea.setBorder(new LineBorder(Color.DARK_GRAY));
        textArea.setText("Frame with resiziable JLayeredPane");
        textPanel.setOpaque(false);
        textPanel.add(textArea, BorderLayout.NORTH);
        Font font = textArea.getFont();
        FontMetrics fontMetrics = textArea.getFontMetrics(font);
        int h = fontMetrics.getHeight() + frame.getInsets().top + 
                textPanel.getInsets().top + textArea.getInsets().top
                + textArea.getInsets().bottom;
        scroll.setBounds(0, h, 400, 300);
        layer.add(textPanel, new Integer(2));
        layer.add(scroll, new Integer(1));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 400);
        frame.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {

                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        resizeAll();
                    }
                });
            }
        });
        frame.setLocationRelativeTo(null);
        frame.add(layer);
        resizeAll();
        frame.setVisible(true);
    }

    void resizeAll() {
        Insets insets = frame.getInsets();
        int w = frame.getWidth() - insets.left - insets.right;
        int h = frame.getHeight() - insets.top - insets.bottom;
        textPanel.setSize(w, h);
        scroll.setSize(w, h - scroll.getY());
        layer.revalidate();
        layer.repaint();
    }

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

            @Override
            public void run() {
                new LayeredPaneWithOverlap().makeUI();
            }
        });
    }
}

答案 1 :(得分:2)

您可以为分层窗格设置布局管理器,javax.swing.OverlayLayout使用完整的可用空间并允许调整大小。

JLayeredPane layer = new JLayeredPane();
layer.setLayout(new OverlayLayout(layer));

您可能不希望子菜单占用全空间。为了避免它,你可以覆盖它的get ... size-methods。或者你可以添加第二个LayeredPane(为它的transperancy和它的layoutmanager),设置一个普通的BoxLayout并使用spacer。

JPanel normalContents = new JPanel();
layer.add(normalContents, JLayeredPane.DEFAULT_LAYER);
JLayeredPane subMenuAuxiliaryLayer = new JLayeredPane()
subMenuAuxiliaryLayer.setLayout(new BoxLayout(subMenuAuxiliaryLayer, BoxLayout.LINE_AXIS));
layer.add(subMenuAuxiliaryLayer, JLayeredPane.PALETTE_LAYER);
JPanel submenuContents = new JPanel();
subMenuAuliliaryLayer.add(submenuContents);
subMenuAuxiliaryLayer.add(Box.createHorizontalGlue());

答案 2 :(得分:1)

contentPanel.setLayout(null); // Absolute positioning of children.

@Override
public void actionPerformed(ActionEvent evt) {
    final JButton btn = (JButton) evt.getSource();
    final int buttonY = btn.getY(); // Must be final for usage in new Runnable object.

    SwingUtilities.invokeLater(new Runnable() { // Return fast from event handling.

        @Override
        public void run() {
            JPanel child = new JPanel();
            child.setBackground(Color.RED); // So we'll see it.
            child.setBounds(0, buttonY, 100, 300);
            contentPanel.removeAll(); // Clear content panel of prior additions.
            contentPanel.add(child); // Add a new panel.
            contentPanel.repaint(10L);
        }
    });
 }

答案 3 :(得分:0)

JLayeredPane通过defualt工作,没有布局管理器,这意味着您使用的是绝对定位而没有调整大小。您可以根据需要添加调整大小侦听器并根据代码调整内部组件的位置和大小。

如果您不想通过代码执行此操作,则需要布局管理器,没有任何花哨的东西,只需要在调整容器大小时填充容器。但事情就是这样......如果你添加一个布局管理器,它会将组件布局好像它们都在一个层中,但是大多数布局管理器不会重叠他们的孩子,所以它们没用。你可以使用的唯一一个是OverlayLayout - 它也可以调整孩子的大小。但是使用带有JLayeredPane的OverlayLayout是过度的。您可以将OverlayLayout与JPanel一起使用。所以,是的,JLayeredPane是没用的。我建议使用带有OverlayLayout的JPanel。

以下是设置方法,以便您可以很好地控制几乎任何重叠的UI场景:使用带有OverlayLayout的JPanel,为每个层都有一个单独的透明JPanel。通过这种方式,您可以在不同的图层上组合各种LayoutManagers,方法是为每个窗格设置不同的布局管理器,包括必要时的绝对定位。然后在代表图层的面板中添加可见组件。不要将它们直接添加到OverlayLayout面板。只需确保您作为图层使用的所有JPanel都具有setAlignmentX,并将Y设置为居中(0.5f),以便在调整大小时填充整个OverlayLayout面板。