2010-11-25 45 views
5

Estoy creando un programa de tipo de piano virtual en Java Swing. Mi área para las teclas del piano en este momento es un JPanel con un BoxLayout horizontal que contiene botones J blancos como teclas blancas. También quiero agregar teclas negras y hacer que se superpongan con las teclas blancas.Haciendo superposición de JButtons

Existen dos enfoques diferentes que he probado. Uno está usando OverlayLayout. Lamentablemente, no hay mucha documentación en línea para el administrador de OverlayLayout, y no está disponible en el generador de la interfaz gráfica de usuario de NetBeans. No tengo ni idea de cómo hacerlo funcionar. Lo segundo que he intentado es usar JLayeredPanes. Parece que tampoco puedo descifrarlo, incluso después de jugar con Netbeans.

Así que creo que mi pregunta es bastante simple. ¿Cuál es el mejor enfoque, si hay uno, para agregar JButtons encima de otros JButtons? ¿O tal vez hay una alternativa al uso de JButtons para teclas de piano?

EDITAR

He combinado de código de dacwe para obtener el resultado que quería y aioobe. Básicamente utilicé el orden z de dacwe con las dimensiones básicas de aioobe (escalado un poco) y la parte del mod 7 también. También agregué algunas variables para aclarar las cosas. Esto es lo que tengo ahora.

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

Gracias chicos! Ahora tengo que adjuntar el oyente y el texto a estos botones de alguna manera.

Respuesta

5

Escribiría un PianoLayoutManager personalizado y colocaría las teclas negras con un orden z más alto que los botones blancos. Crear su propia clase "restricción" que le permite añadir componentes como esto:

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

De Using Swing Components tutorial trail

Nota: El orden z determina el orden en que los componentes están pintados. El componente con el orden z más alto pinta primero y el componente con las pinturas con el orden z más bajo duran. Cuando los componentes se superponen, el componente con el orden z más bajo pinta sobre el componente con un orden z más alto.

Aquí está un truco feo que utiliza null-layout para empezar.

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

enter image description here

+0

Componentes z orden están en mal estado !! – dacwe

+0

¿usted piensa? Creo que se ve bien ... :) – aioobe

+0

Ehhh, compilado, ejecutado y movido el mouse sobre él ... hará que los botones estén en el orden incorrecto cuando se vuelvan a renderizar. – dacwe

0

diseño GridBag sí permite la superposición widget de; Podría usar tramos superpuestos para construir el diseño que desea. Pero sí, escribir el propio administrador de diseño sería mejor.

0

He hecho un par de juegos en Swing, y me parece más fácil simplemente no usar un administrador de diseño o hacer uno propio. Por ejemplo, tengo un juego de cartas y un administrador de diseño personalizado que observa dónde se ha jugado la carta y la coloca en función de eso y del tamaño actual del panel.

1

Además de escribir su propio administrador de disposición, puede usar un null LayoutManager (es decir, sin administración automática de disposición) y colocar las claves manualmente. Luego use setComponentZOrder en el contenedor para asegurarse de que las teclas negras aparecen sobre las blancas.

+0

¿Cómo manejarías los problemas que tiene aioobe? – dacwe

+0

Hmm, en mi OSX ejecutando 1.6.0_22, no veo ningún problema con el orden z. – jackrabbit

3

Este es un ejemplo de layeredpane (funciona como se espera):

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

Sin embargo, es necesario disponer las teclas de piano en el orden correcto (:)):

alt text

+0

¡Excelente! Esto puede parecer una pregunta tonta, pero ¿puedo asignar ActionListeners y texto a esos JButtons anónimos? – aharlow

+0

¡Publique otra pregunta para que consiga una aceptación! ;) bueno sí, solo agregue 'b.addActionListener (new ActionListener() {public void actionPerformed (ActionEvent ae) {/ * su código * /}});' – dacwe

0

Echa un vistazo a la solución de Darryl (la última respuesta) en este posting. Se pone complicado y utiliza un "Botón" como el botón negro para que se coloque sobre el "JButton" blanco. Probablemente esto no funcionará en las nuevas versiones del JDK que permiten mezclar los componentes AWT y Swing.

Sin embargo, la parte clara es que las teclas realmente producen un sonido cuando se hace clic.