我需要在JScrollPane中使用JLayeredPane创建一个包含四个八度的虚拟钢琴,这样最初会显示一个八度音阶,并且可以水平滚动以查看其他八度音阶。我的代码只显示一个八度音,不显示滚动条和其他八度音程。以下代码有什么问题?
class PianoLayout extends JScrollPane
{
public PianoLayout()
{
initComponents();
}
private void initComponents()
{
JLayeredPane layer = new JLayeredPane();
//ScrollableLayeredPane layer = new ScrollableLayeredPane();
layer.setSize(1120,150);
JButton[] keys = new JButton[48];
int keyIndex = 0, i;
for(i=0;i<28;i++)
{
keys[keyIndex] = createWhiteKey(i);
layer.add(keys[keyIndex], 0, -1);
keyIndex+=1;
if(i%7!=2 && i%7!=6)
{
keys[keyIndex] = createBlackKey(i);
layer.add(keys[keyIndex], 1, -1);
keyIndex+=1;
}
}
this.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.setViewportView(layer);
setSize(280, 150);
setLocation(110,100);
}
private JButton createWhiteKey(int i)
{
JButton whiteKey = new JButton();
whiteKey.setBackground(Color.WHITE);
whiteKey.setLocation(i*40,0);
whiteKey.setSize(40, 150);
return whiteKey;
}
private JButton createBlackKey(int i)
{
JButton blackKey = new JButton();
blackKey.setBackground(Color.BLACK);
blackKey.setLocation(25 + i*40,0);
blackKey.setSize(30, 90);
return blackKey;
}
}
public class VirtualPiano
{
public static void main(String[] args)
{
JPanel panel = new JPanel(null);
JFrame mainFrame = new JFrame();
PianoLayout pianoLayout = new PianoLayout();
mainFrame.add(panel);
panel.add(pianoLayout);
mainFrame.setSize(500,500);
mainFrame.setVisible(true);
}
答案 0 :(得分:1)
这是我很久以前在论坛上发现的一个例子。我对音乐一无所知,所以我不明白逻辑如何创造声音和键。
但我只是更改了代码以实现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;
}
}
这不是一个纯粹的解决方案,因为真的应该使用自定义布局管理器来布局组件并确定首选大小。