使JButton重叠

我正在Java Swing中创建一个虚拟钢琴类型程序。 我现在的钢琴键区域是一个JPanel,其水平BoxLayout包含白色JButtons作为白键。 我也想添加黑键,让它们与白键重叠。

我尝试过两种不同的方法。 一个是使用OverlayLayout。 遗憾的是,OverlayLayout管理器的在线文档并不多,而且NetBeans GUI构建器中没有该文档。 我不知道如何让它发挥作用。 我尝试的第二件事是使用JLayeredPanes。 即使在Netbeans中弄乱它之后,我似乎无法想出那个。

所以我认为我的问题非常简单。 如果有的话,在其他JButton之上添加JButton的最佳方法是什么? 或者也许有一个替代使用JButtons钢琴键?

编辑

我结合了aioobe和dacwe的代码来获得我想要的结果。 我基本上使用dacwe的z-ordering与aioobe的基本尺寸(按比例放大)和mod 7部分。 我还添加了一些变量以使事情更清晰。 这就是我现在拥有的。

import javax.swing.*; import java.awt.Color; public class Test2 { public static void main(String[] args) { JFrame frame = new JFrame("Test"); JLayeredPane panel = new JLayeredPane(); frame.add(panel); int maxKeys = 8; int width = 60; int height = 240; for (int i = 0; i < maxKeys; i++) { JButton b = new JButton(); b.setBackground(Color.WHITE); b.setLocation(i * width, 0); b.setSize(width, height); panel.add(b, 0, -1); } int width2 = 48; int height2 = 140; for (int i = 0; i < maxKeys; i++) { int j = i % 7; if (j == 2 || j == 6) continue; JButton b = new JButton(); b.setBackground(Color.BLACK); b.setLocation(i*(width) + (width2*3/4), 0); b.setSize(width2, height2); panel.add(b, 1, -1); } frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(500,280); frame.setVisible(true); } } 

多谢你们! 现在我需要以某种方式将监听器和文本附加到这些按钮。

我会编写一个自定义的PianoLayoutManager并使用比白色按钮更高的z顺序定位黑键。 创建自己的“约束”类,允许您添加如下组件:

 add(new WhiteKey(), new PianoLayoutConstraint(WHITE, 1); add(new WhiteKey(), new PianoLayoutConstraint(WHITE, 2); ... add(new WhiteKey(), new PianoLayoutConstraint(WHITE, n); add(new BlackKey(), new PianoLayoutConstraint(BLACK, 1); add(new BlackKey(), new PianoLayoutConstraint(BLACK, 2); ... add(new BlackKey(), new PianoLayoutConstraint(BLACK, m); 

从使用Swing组件教程开始

注意: z顺序决定了组件的绘制顺序。 具有最高z次序涂料的组件首先涂漆,具有最低z次序涂料的组件持续。 在组件重叠的情况下,具有较低z次序的组件在具有较高z次序的组件上绘制。

这是一个丑陋的黑客,它使用null-layout来帮助你入门。

 import java.awt.Color; import javax.swing.*; class PianoComponent extends JPanel { PianoComponent() { setLayout(null); for (int i = 0; i < 20; i++) { JButton key = new JButton(); key.setBackground(Color.WHITE); key.setLocation(i * 20, 0); key.setSize(20, 120); add(key); setComponentZOrder(key, i); } for (int i = 0; i < 20; i++) { int j = i % 7; if (j == 2 || j == 6) continue; JButton key = new JButton(); key.setBackground(Color.BLACK); key.setLocation(i * 20 + 12, 0); key.setSize(16, 80); add(key); setComponentZOrder(key, 0); } } } public class Test { public static void main(String[] args) { JFrame jf = new JFrame("Piano!"); jf.setSize(400, 200); jf.add(new PianoComponent()); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } } 

在此处输入图像描述

这是layeredpane的一个例子(它按预期工作):

 public static void main(String[] args) { JFrame frame = new JFrame("Test"); JLayeredPane panel = new JLayeredPane(); frame.add(panel); for (int i = 0; i < 8; i++) { JButton b = new JButton(); b.setBackground(Color.WHITE); b.setLocation(i * 20, 0); b.setSize(20, 100); panel.add(b, 0, -1); } for (int i = 0; i < 4; i++) { JButton b = new JButton(); b.setBackground(Color.BLACK); b.setLocation(10 + i * 40, 0); b.setSize(20, 70); panel.add(b, 1, -1); } frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 300); frame.setVisible(true); } 

但是,您需要按正确的顺序布置钢琴键(:)):

替代文字

除了编写自己的布局管理器之外,您可以使用null LayoutManager(即没有自动布局管理)并手动定位键。 然后在容器上使用setComponentZOrder以确保黑键出现在白色上方。

GridBag布局确实允许窗口小部件重叠; 您可以使用重叠跨度来构建所需的布局。 但是,是的,编写自己的布局管理器会更好。

我在Swing中做了几个游戏,我发现不使用布局管理器或制作自己的游戏更容易。 例如,我有一个纸牌游戏和一个自定义布局管理器,可以查看卡片的播放位置,并根据该卡片和当前面板大小对其进行定位。

查看该post中的 Darryl的解决方案(最后一个回复)。 它变得棘手并使用“按钮”作为黑色按钮,因此它绘制在白色“JButton”之上。 这可能不适用于允许混合AWT和Swing组件的JDK的新版本。

然而,整洁的部分是按键实际上在点击时产生声音。