2010-11-25 15 views
5

Ich erstelle ein virtuelles Klavier-Typ-Programm in Java Swing. Mein Bereich für die Klaviertasten ist jetzt ein JPanel mit einer horizontalen BoxLayout, die weiße JButtons als weiße Tasten enthält. Ich möchte auch schwarze Tasten hinzufügen und sie mit den weißen Tasten überlappen lassen.Making JButtons überlappen

Es gibt zwei verschiedene Ansätze, die ich ausprobiert habe. Einer verwendet das OverlayLayout. Leider gibt es nicht viel Dokumentation online für den OverlayLayout-Manager, und es ist nicht im NetBeans-GUI-Builder verfügbar. Ich habe keine Ahnung, wie es funktioniert. Die zweite Sache, die ich ausprobiert habe, ist JLayeredPanes. Ich kann mir das auch nicht vorstellen, selbst nachdem ich es in Netbeans damit zu tun hatte.

Also ich denke meine Frage ist ziemlich einfach. Was ist der beste Ansatz, wenn es einen gibt, JButtons über anderen JButtons hinzuzufügen? Oder gibt es eine Alternative zur Verwendung von JButtons für Klaviertasten?

EDIT

I kombiniert habe aioobe der und Code des dacwe das Ergebnis, das ich wollte zu bekommen. Ich benutzte im Grunde Dacwes Z-Ordering mit aioobes Grunddimensionen (etwas vergrößert) und dem Mod-7-Part auch. Ich habe auch einige Variablen hinzugefügt, um die Dinge klarer zu machen. Das habe ich jetzt.

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

Danke Jungs! Jetzt muss ich irgendwie den Hörer und den Text an diese Buttons anhängen.

Antwort

5

Ich würde eine benutzerdefinierte PianoLayoutManager schreiben und die schwarzen Tasten mit einer höheren Z-Reihenfolge als die weißen Tasten positionieren. Erstellen Sie Ihre eigenen „Zwang“ Klasse, die Sie Komponenten wie diese hinzufügen können:

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

Von Using Swing Components tutorial trail

Hinweis: Die Z-Reihenfolge bestimmt die Reihenfolge, dass die Komponenten lackiert. Die Komponente mit den Farben mit der höchsten z-Reihenfolge und die Komponente mit den Farben mit der niedrigsten z-Reihenfolge werden zuerst angezeigt. Wo Komponenten sich überlappen, überzieht die Komponente mit der niedrigeren z-Reihenfolge die Komponente mit der höheren z-Reihenfolge.

Hier ist ein hässlicher Hack, der Null-Layout verwendet, um loszulegen.

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

Komponenten z Bestellung sind durcheinander !! – dacwe

+0

Sie denken? Ich denke, es sieht gut aus ... :) – aioobe

+0

Ehhh, kompiliert und ausgeführt und Maus darüber bewegt ... es wird die Schaltflächen in der falschen Reihenfolge rendern, wenn sie neu gerendert werden. – dacwe

0

GridBag Layout hat Widget überlappende ermöglichen; Sie könnten überlappende Spannen verwenden, um das gewünschte Layout zu erstellen. Aber ja, einen eigenen Layout-Manager zu schreiben wäre schöner.

0

Ich habe ein paar Spiele in Swing gemacht, und ich finde es einfacher, einfach keinen Layout-Manager zu verwenden oder eigene zu erstellen. Zum Beispiel habe ich ein Kartenspiel und einen benutzerdefinierten Layout-Manager, der sich anschaut, wo die Karte gespielt wurde und positioniert sie basierend auf dieser und der aktuellen Panelgröße.

1

Abgesehen von Ihrem eigenen Layout-Manager können Sie einfach einen null LayoutManager (also keine automatische Layoutverwaltung) verwenden und die Schlüssel manuell positionieren. Verwenden Sie dann setComponentZOrder auf dem Container, um sicherzustellen, dass die schwarzen Tasten über den weißen angezeigt werden.

+0

Wie würden Sie mit den Problemen umgehen, die aioobe hat? – dacwe

+0

Hmm, auf meinem OSX läuft 1.6.0_22, ich sehe keine Probleme mit der z-Ordnung. – jackrabbit

3

Dies ist ein Beispiel für layeredpane (es funktioniert wie erwartet):

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

Allerdings müssen Sie die Klaviertasten in der richtigen Reihenfolge legen (:)):

alt text

+0

Ausgezeichnet! Das mag eine dumme Frage sein, aber kann ich diesen anonymen JButtons ActionListeners und Text zuordnen? – aharlow

+0

Poste eine andere Frage, damit ich ein Akzeptieren bekomme! ;) Nun ja, füge einfach 'b.addActionListener (neuer ActionListener() {public void actionPerformed (ActionEvent ae) {/ * dein Code * /}})' 'hinzu – dacwe

0

Überprüfen Sie die Lösung von Darryl (die letzte Antwort) in diesem posting. Es wird knifflig und verwendet einen "Button" als den schwarzen Button, so dass es über dem weißen "JButton" malt. Dies wird wahrscheinlich in neuen Versionen des JDK nicht funktionieren, die AWT- und Swing-Komponenten mischen können.

Der nette Teil ist jedoch, dass die Tasten tatsächlich einen Ton erzeugen, wenn sie geklickt werden.