如何使用JScrollPane和JLayeredPane创建钢琴 [英] How to create a Piano using JScrollPane and JLayeredPane

查看:82
本文介绍了如何使用JScrollPane和JLayeredPane创建钢琴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用JScrollPane内的JLayeredPane创建一个包含四个八度音阶的虚拟钢琴,以便最初显示一个八度音阶,并且可以水平滚动查看其他八度音阶.我的代码仅显示一个八度,不显示滚动条和其他八度.以下代码有什么问题?

I need to create a virtual piano containing four octaves using JLayeredPane inside a JScrollPane such that one octave is shown initially, and can be scrolled horizontally to see the other octaves. My code displays only one octave and does not show the scrollbar and the other octaves. What is the problem with the following code?

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);
}

推荐答案

这是我很久以前在论坛上发现的一个示例.我对音乐一无所知,所以我不了解创建声音和键的逻辑原理.

Here is an example I found on a forum a long time ago. I know nothing about music so I don't understand how the logic works to create the sounds and keys.

但是我只是更改了代码以实现getPreferredSize()方法,以便滚动窗格可以正常工作:

But I did just change the code to implement the getPreferredSize() method so that the scrollpane will work properly:

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;
    }
}

这不是一个纯粹的解决方案,因为确实应该使用自定义布局管理器来布局组件并确定首选大小.

This is not a pure solution, because a custom layout manager really should be used to lay out the components and determine a preferred size.

这篇关于如何使用JScrollPane和JLayeredPane创建钢琴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆