Java Swing - 如何在另一个面板上显示一个面板?
Posted
技术标签:
【中文标题】Java Swing - 如何在另一个面板上显示一个面板?【英文标题】:Java Swing - how to show a panel on top of another panel? 【发布时间】:2010-10-25 13:20:26 【问题描述】:我希望有一个内部(非窗口)对话框来询问成员输入。我希望将对话框集中放置在现有的 JPanel 上。
我查看了layeredpanes,这些似乎无法使用,因为所有窗格中只有一个布局管理器(或没有布局管理器)。我想我可以尝试覆盖 JLayeredPane 并提供自定义布局,但这似乎很极端。
Glass panes 似乎也不合适。
如何做到这一点? Swing 中没有可用的 z-index 概念吗?
编辑
分层窗格不合适的原因是由于缺少每层的布局管理器。面板可调整大小,面板 A 应保持在 100% 的区域,面板 B 应保持居中。
【问题讨论】:
请参阅——作为一个选项——如何(非常简单地)扩展 JLayeredPane 以接受任何类型的 LayouManager。 ***.com/questions/42413590/… 【参考方案1】:我认为 LayeredPane 是您最好的选择。您需要第三个面板来包含 A 和 B。这第三个面板将是 layeredPane,然后面板 A 和 B 仍然可以有一个不错的 LayoutManagers。您所要做的就是将 B 置于 A 之上,在 Swing 路径中有很多关于如何做到这一点的示例。 Tutorial for positioning without a LayoutManager.
public class Main
private JFrame frame = new JFrame();
private JLayeredPane lpane = new JLayeredPane();
private JPanel panelBlue = new JPanel();
private JPanel panelGreen = new JPanel();
public Main()
frame.setPreferredSize(new Dimension(600, 400));
frame.setLayout(new BorderLayout());
frame.add(lpane, BorderLayout.CENTER);
lpane.setBounds(0, 0, 600, 400);
panelBlue.setBackground(Color.BLUE);
panelBlue.setBounds(0, 0, 600, 400);
panelBlue.setOpaque(true);
panelGreen.setBackground(Color.GREEN);
panelGreen.setBounds(200, 100, 100, 100);
panelGreen.setOpaque(true);
lpane.add(panelBlue, new Integer(0), 0);
lpane.add(panelGreen, new Integer(1), 0);
frame.pack();
frame.setVisible(true);
/**
* @param args the command line arguments
*/
public static void main(String[] args)
new Main();
您可以使用 setBounds 将面板定位在分层窗格内并设置它们的大小。
编辑以反映对原始帖子的更改 您将需要添加组件侦听器,以检测何时调整父容器的大小,然后动态更改面板 A 和 B 的边界。
【讨论】:
嗨,这是我最初追求的途径,但我不知道如何在不使用 setBounds 的情况下使 A 和 B 正常运行。 JLayeredPane 的文档提到“Java 平台提供的所有布局管理器都将组件排列为好像它们都在一层上一样。”。 是的,这是正确的。要定位 A 和 B,您需要使用 setBounds。面板 A 和 B 仍然可以具有您想要在其中放置组件的任何 LayoutManager。这能回答你的问题吗? 我试图在 setBounds 上使用布局管理器的原因是面板可以调整大小。可能扩展 JLayeredPane、监听组件更改并在其子级上调用 setBounds 是解决此问题的正确方法。 (我也会编辑原始问题以澄清这一点。)【参考方案2】:您可以像这样添加未修饰的 JDialog:
import java.awt.event.*;
import javax.swing.*;
public class TestSwing
public static void main(String[] args) throws Exception
JFrame frame = new JFrame("Parent");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
final JDialog dialog = new JDialog(frame, "Child", true);
dialog.setSize(300, 200);
dialog.setLocationRelativeTo(frame);
JButton button = new JButton("Button");
button.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
dialog.dispose();
);
dialog.add(button);
dialog.setUndecorated(true);
dialog.setVisible(true);
【讨论】:
谢谢,不幸的是,这会创建一个新窗口,+1 表示未装饰,效果非常好。 为什么这是个问题?现在我再次查看您的问题,您可能希望使对话框非模态并在调整父框架大小时重新定位它。 这是一个要求。对话框/窗口对此面板没有意义。【参考方案3】:我只是想补充一下,在 Swing 中有一个 Z 顺序的概念,请参阅 [java.awt.Component#setComponentZOrder][1]
影响组件在其父组件数组中的位置,从而决定绘制顺序。
请注意,您应该覆盖 javax.swing.JComponent#isOptimizedDrawingEnabled 以在父容器中返回 false 以使您的重叠组件正确重绘,否则它们的重绘将相互破坏。 (JComponents 假设没有重叠的子节点,除非 isOptimizedDrawingEnabled 返回 false)
[1]:http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Container.html#setComponentZOrder(java.awt.Component,整数)
【讨论】:
【参考方案4】:在现有 JPanel 上使用 1 x 1 GridLayout,然后将您的 Panel 添加到该 JPanel。 1 比 1 的 GridLayout 的唯一问题是您将无法在 JPanel 上放置其他项目。在这种情况下,您必须找出合适的布局。您使用的每个面板都可以使用自己的布局,这样就不会出现问题。
我对这个问题的理解正确吗?
【讨论】:
谢谢,我在上面添加了一个图表来澄清。基本上它是将组件放在彼此之上(z 索引),我不确定。 哦,好吧,我明白了,我的错误。感谢您的额外澄清。【参考方案5】:JOptionPane.showInternalInputDialog 可能会做你想要的。如果没有,了解它缺少什么会很有帮助。
【讨论】:
谢谢,据我了解,它会显示一个内部框架,该框架具有窗口的外观和感觉。我真的需要面板提供的完全自定义。【参考方案6】:这里可能还有另一个布局管理器:Overlay Layout 这是一个简单的教程:OverlayLayout: for layout management of components that lie on top of one another。 覆盖布局允许您将面板放置在彼此之上,并在每个面板内设置布局。您还可以分别设置每个面板的大小和位置。
(我几年前回答这个问题的原因是因为我偶然发现了同样的问题,而且我很少看到 *** 上提到 Overlay Layout,虽然它似乎有很好的记录。希望这个可能会帮助其他一直在寻找它的人。)
【讨论】:
以上是关于Java Swing - 如何在另一个面板上显示一个面板?的主要内容,如果未能解决你的问题,请参考以下文章
java swing问题:JFrame根面板不透明且可见,内容面板不透明且可见,层面板透明且可见,
如何从另一个子 JPanel(Java Swing)中的输入触发一个子 JPanel 中的操作?