Question

I am trying to create a virtual piano using java. i am having an issue with the layout however.

Here are the snippets which should be of interest:

The initialisation:

public class Piano extends JFrame implements KeyListener {
private PianoKeyboard keyboardPanel;    
    public Piano() {
        super();
        this.setTitle("Piano");
        this.setName("Piano");      
        this.setSize(850,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        keyboardPanel = new PianoKeyboard(0);
        keyboardPanel.addListener(this);
        this.getContentPane().add(keyboardPanel);
        this.setVisible(true);
    }
}

The Layerd Pane:

public class PianoKeyboard extends JLayeredPane implements MouseListener{
    public PianoKeyboard(int tempo){
        super();
        this.setEnabled(true);
        this.setVisible(true);
        createKeyboard();
    }
privte void createKeyboard() {
        setLayout(new GridLayout(25, 0));           
        int loc = 0;
        for(int i = 0; i < 25; i++){
            PianoKey k = new PianoKey(i+1,tempo);
            k.addMouseListener(this);
            if(i ==0){
                k.setLocation(0);
            }else{
                if(PianoKey.isWhite(i+1) && PianoKey.isWhite(i)){
                    loc+=54;
                }else if(PianoKey.isWhite(i+1) && !PianoKey.isWhite(i)){
                    loc+=15;
                }else if(!PianoKey.isWhite(i+1) && PianoKey.isWhite(i)){
                    loc+=39;
                }else if(!PianoKey.isWhite(i+1) && !PianoKey.isWhite(i)){
                    // impossible
                } 
                k.setLocation(loc);
            }
            add(k,(PianoKey.isWhite(i+1))?new Integer(0):new Integer(1));
        }
    }
}

Here is the comonent for the individual key:

public class PianoKey extends JComponent {
public PianoKey(int pitch, int tempo) {
        super();
        this.pitch = pitch;
        ClassLoader cl = this.getClass().getClassLoader();
        try {
            BufferedImage key;
            if (isWhite(this.pitch)) {
                key = ImageIO.read(cl.getResource(IMAGE_DIRECTORY
                        + "/key/white.png"));
                height = 150;
                width = 54;
            } else {
                key = ImageIO.read(cl.getResource(IMAGE_DIRECTORY
                        + "/key/black.png"));
                height = 89;
                width = 29;
            }
            Dimension sz = new Dimension(width, height);
            System.out.println("Setting to: "+width+"; "+height);
            setPreferredSize(sz);
            setMinimumSize(sz);
            setMaximumSize(sz);
            setBounds(0,0,width,height);
            setImage(key);
        } catch (IOException e) {
            Logger.getLogger(MusicNote.class).log(Level.WARNING,
                    "IO Error. Music Not duration. failed finding     image");
        }
    }
@Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        BufferedImage key = (BufferedImage) getImage();
        g.drawImage(key, offset, 0, width,height, null);

    }

    int offset = 0;
    public void setLocation(int x){
        offset = x;
        setBounds(offset,0,width,height);
    }
 }

Current Piano Layout

The y offset seems to be changing progressively and the height is completely wrong. the images have the following sizes: Black keys (29x89), White Keys (54x150)

If the gridlayout in the layered pane is removed, the notes i believe are all stacked on top of each other which makes only one note visible and clickable.

Was it helpful?

Solution

You're GridLayout is reversed. You have

setLayout(new GridLayout(25, 0)); 

That will create 25 different lines. That's why your keys are "stepping down" - each are on a separate line

setLayout(new GridLayout(1, 25));

The above will give you one line with 25 columns

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top