Java 如何使用JScrollPane和JLayeredPane创建钢琴
我需要在JScrollPane中使用JLayeredPane创建一个包含四个八度音阶的虚拟钢琴,这样一个八度音阶最初会显示,并且可以水平滚动以查看其他八度音阶。我的代码只显示一个八度,不显示滚动条和其他八度。以下代码有什么问题?Java 如何使用JScrollPane和JLayeredPane创建钢琴,java,swing,jscrollpane,jlayeredpane,piano,Java,Swing,Jscrollpane,Jlayeredpane,Piano,我需要在JScrollPane中使用JLayeredPane创建一个包含四个八度音阶的虚拟钢琴,这样一个八度音阶最初会显示,并且可以水平滚动以查看其他八度音阶。我的代码只显示一个八度,不显示滚动条和其他八度。以下代码有什么问题? class PianoLayout扩展了JScrollPane { 公共钢琴 { 初始化组件(); } 私有组件() { JLayeredPane层=新的JLayeredPane(); //ScrollableLayeredPane layer=新的Scrollabl
class PianoLayout扩展了JScrollPane
{
公共钢琴
{
初始化组件();
}
私有组件()
{
JLayeredPane层=新的JLayeredPane();
//ScrollableLayeredPane layer=新的ScrollableLayeredPane();
图层设置尺寸(1120150);
JButton[]键=新JButton[48];
int-keyIndex=0,i;
例如(i=0;i这是我很久以前在一个论坛上找到的一个例子。我对音乐一无所知,所以我不明白创建声音和键的逻辑是如何工作的
但我只是更改了代码以实现getPreferredSize()
方法,以便滚动窗格能够正常工作:
import java.awt.*;
import java.awt.event.*;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Synthesizer;
import javax.swing.*;
public class MidiPiano implements MouseListener {
final int OCTAVES = 4; // change as desired
private WhiteKey[] whites = new WhiteKey [7 * OCTAVES + 1];
private BlackKey[] blacks = new BlackKey [5 * OCTAVES];
MidiChannel channel;
public MidiPiano () {
try {
Synthesizer synth = MidiSystem.getSynthesizer ();
synth.open ();
synth.loadAllInstruments (synth.getDefaultSoundbank ());
Instrument [] insts = synth.getLoadedInstruments ();
MidiChannel channels[] = synth.getChannels ();
for (int i = 0; i < channels.length; i++) {
if (channels [i] != null) {
channel = channels [i];
break;
}
}
for (int i = 0; i < insts.length; i++) {
if (insts [i].toString ()
.startsWith ("Instrument MidiPiano")) {
channel.programChange (i);
break;
}
}
} catch (MidiUnavailableException ex) {
ex.printStackTrace ();
}
}
public void mousePressed (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOn (key.getNote (), 127);
}
public void mouseReleased (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOff (key.getNote ());
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
private void createAndShowGUI () {
JPanel contentPane = new JPanel(null)
{
@Override
public Dimension getPreferredSize()
{
int count = getComponentCount();
Component last = getComponent(count - 1);
Rectangle bounds = last.getBounds();
int width = 10 + bounds.x + bounds.width;
int height = 10 + bounds.y + bounds.height;
return new Dimension(width, height);
}
@Override
public boolean isOptimizedDrawingEnabled()
{
return false;
}
};
for (int i = 0; i < blacks.length; i++) {
blacks [i] = new BlackKey (i);
contentPane.add (blacks [i]);
blacks [i].addMouseListener (this);
}
for (int i = 0; i < whites.length; i++) {
whites [i] = new WhiteKey (i);
contentPane.add (whites [i]);
whites [i].addMouseListener (this);
}
JFrame frame = new JFrame("Midi Piano");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//frame.add( contentPane );
frame.add( new JScrollPane(contentPane) );
frame.pack();
frame.setLocationRelativeTo (null);
frame.setVisible(true);
}
public static void main (String[] args) {
SwingUtilities.invokeLater (new Runnable () {
public void run () {
new MidiPiano ().createAndShowGUI ();
}
});
}
}
interface Key {
// change WD to suit your screen
int WD = 16;
int HT = (WD * 9) / 2;
// change baseNote for starting octave
// multiples of 16 only
int baseNote = 48;
int getNote ();
}
class BlackKey extends JButton implements Key {
final int note;
public BlackKey (int pos) {
note = baseNote + 1 + 2 * pos + (pos + 3) / 5 + pos / 5;
int left = 10 + WD
+ ((WD * 3) / 2) * (pos + (pos / 5)
+ ((pos + 3) / 5));
setBackground (Color.BLACK);
setBounds (left, 10, WD, HT);
}
public int getNote () {
return note;
}
}
class WhiteKey extends JButton implements Key {
static int WWD = (WD * 3) / 2;
static int WHT = (HT * 3) / 2;
final int note;
public WhiteKey (int pos) {
note = baseNote + 2 * pos
- (pos + 4) / 7
- pos / 7;
int left = 10 + WWD * pos;
// I think metal looks better!
//setBackground (Color.WHITE);
setBounds (left, 10, WWD, WHT);
}
public int getNote () {
return note;
}
}
import java.awt.*;
导入java.awt.event.*;
导入javax.sound.midi.Instrument;
导入javax.sound.midi.MidiChannel;
导入javax.sound.midi.midi系统;
导入javax.sound.midi.MidiUnavailableException;
导入javax.sound.midi.Synthesizer;
导入javax.swing.*;
公共类midistener{
最终整数倍频程=4;//根据需要更改
专用白键[]白色=新白键[7*八度+1];
专用黑键[]黑色=新黑键[5*八度];
中音信道;
公共MIDI钢琴(){
试一试{
合成器synth=MidiSystem.getSynthesizer();
synth.open();
synth.loadAllInstruments(synth.getDefaultSoundbank());
仪器[]仪器=synth.getLoadedInstruments();
MidiChannel channels[]=synth.getChannels();
对于(int i=0;i
这不是一个纯粹的解决方案,因为确实应该使用自定义布局管理器来布局组件并确定首选大小。不要从JScrollPane
扩展,这不是该组件的工作方式,而是从JPanel
扩展,然后将其应用于JScrollPane
。有关更多详细信息,请参阅etailsJScrollPane
将使用首选尺寸的组件进行确定
import java.awt.*;
import java.awt.event.*;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Synthesizer;
import javax.swing.*;
public class MidiPiano implements MouseListener {
final int OCTAVES = 4; // change as desired
private WhiteKey[] whites = new WhiteKey [7 * OCTAVES + 1];
private BlackKey[] blacks = new BlackKey [5 * OCTAVES];
MidiChannel channel;
public MidiPiano () {
try {
Synthesizer synth = MidiSystem.getSynthesizer ();
synth.open ();
synth.loadAllInstruments (synth.getDefaultSoundbank ());
Instrument [] insts = synth.getLoadedInstruments ();
MidiChannel channels[] = synth.getChannels ();
for (int i = 0; i < channels.length; i++) {
if (channels [i] != null) {
channel = channels [i];
break;
}
}
for (int i = 0; i < insts.length; i++) {
if (insts [i].toString ()
.startsWith ("Instrument MidiPiano")) {
channel.programChange (i);
break;
}
}
} catch (MidiUnavailableException ex) {
ex.printStackTrace ();
}
}
public void mousePressed (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOn (key.getNote (), 127);
}
public void mouseReleased (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOff (key.getNote ());
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
private void createAndShowGUI () {
JPanel contentPane = new JPanel(null)
{
@Override
public Dimension getPreferredSize()
{
int count = getComponentCount();
Component last = getComponent(count - 1);
Rectangle bounds = last.getBounds();
int width = 10 + bounds.x + bounds.width;
int height = 10 + bounds.y + bounds.height;
return new Dimension(width, height);
}
@Override
public boolean isOptimizedDrawingEnabled()
{
return false;
}
};
for (int i = 0; i < blacks.length; i++) {
blacks [i] = new BlackKey (i);
contentPane.add (blacks [i]);
blacks [i].addMouseListener (this);
}
for (int i = 0; i < whites.length; i++) {
whites [i] = new WhiteKey (i);
contentPane.add (whites [i]);
whites [i].addMouseListener (this);
}
JFrame frame = new JFrame("Midi Piano");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//frame.add( contentPane );
frame.add( new JScrollPane(contentPane) );
frame.pack();
frame.setLocationRelativeTo (null);
frame.setVisible(true);
}
public static void main (String[] args) {
SwingUtilities.invokeLater (new Runnable () {
public void run () {
new MidiPiano ().createAndShowGUI ();
}
});
}
}
interface Key {
// change WD to suit your screen
int WD = 16;
int HT = (WD * 9) / 2;
// change baseNote for starting octave
// multiples of 16 only
int baseNote = 48;
int getNote ();
}
class BlackKey extends JButton implements Key {
final int note;
public BlackKey (int pos) {
note = baseNote + 1 + 2 * pos + (pos + 3) / 5 + pos / 5;
int left = 10 + WD
+ ((WD * 3) / 2) * (pos + (pos / 5)
+ ((pos + 3) / 5));
setBackground (Color.BLACK);
setBounds (left, 10, WD, HT);
}
public int getNote () {
return note;
}
}
class WhiteKey extends JButton implements Key {
static int WWD = (WD * 3) / 2;
static int WHT = (HT * 3) / 2;
final int note;
public WhiteKey (int pos) {
note = baseNote + 2 * pos
- (pos + 4) / 7
- pos / 7;
int left = 10 + WWD * pos;
// I think metal looks better!
//setBackground (Color.WHITE);
setBounds (left, 10, WWD, WHT);
}
public int getNote () {
return note;
}
}