5

JavaSwingで仮想ピアノタイプのプログラムを作成しています。現在のピアノキーの私の領域は、白いキーとして白いJButtonを含む水平のBoxLayoutを持つJPanelです。黒のキーも追加して、白のキーと重ねてもらいたいです。

私が試した2つの異なるアプローチがあります。1つはOverlayLayoutを使用しています。残念ながら、OverlayLayoutマネージャのオンラインドキュメントはあまりなく、NetBeansGUIビルダーでは利用できません。私はそれを機能させる方法の手がかりを持っていません。私が試した2番目のことは、JLayeredPanesを使用することです。Netbeansでそれをいじった後でも、私はそれを理解できないようです。

ですから、私の質問は非常に単純だと思います。他のJButtonの上にJButtonを追加するための最良のアプローチは、もしあれば、何ですか?それとも、ピアノの鍵盤にJButtonを使用する代わりの方法がありますか?

編集

aioobeとdacweのコードを組み合わせて、希望する結果を得ました。私は基本的に、aioobeの基本的な寸法(少し拡大)とmod7の部分を使用したdacweのz-orderingを使用しました。また、物事をより明確にするためにいくつかの変数を追加しました。これは私が今持っているものです。

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

みんなありがとう!次に、リスナーとテキストをこれらのボタンに何らかの方法で添付する必要があります。

4

6 に答える 6

5

カスタムPianoLayoutManagerを作成し、黒いキーを白いボタンよりも高い z オーダーで配置します。次のようなコンポーネントを追加できる独自の「制約」クラスを作成します。

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

Using Swing Components チュートリアルトレイルから

注: z オーダーは、コンポーネントがペイントされる順序を決定します。z オーダーが最も高いコンポーネントが最初にペイントされ、z オーダーが最も低いコンポーネントが最後にペイントされます。コンポーネントが重なっている場所では、z オーダーが低いコンポーネントが z オーダーが高いコンポーネントを塗りつぶします。

null-layout を使用して開始する醜いハックを次に示します。

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

ここに画像の説明を入力

于 2010-11-25T19:34:30.990 に答える
2

これは、layeredpane の例です (期待どおりに動作します)。

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

ただし、ピアノのキーを正しい順序で配置する必要があります (:)) :

代替テキスト

于 2010-11-25T20:08:47.537 に答える
1

独自のレイアウト マネージャーを作成する以外に、nullLayoutManager (つまり、自動レイアウト管理なし) を使用して、キーを手動で配置することもできます。次にsetComponentZOrder、コンテナーで を使用して、黒鍵が白鍵の上に表示されるようにします。

于 2010-11-25T19:39:11.123 に答える
0

GridBag レイアウトは、ウィジェットのオーバーラップを許可します。重なり合うスパンを使用して、必要なレイアウトを構築できます。しかし、はい、独自のレイアウトマネージャーを作成する方が良いでしょう。

于 2010-11-25T19:35:35.860 に答える
0

私は Swing でいくつかのゲームを実行しましたが、レイアウト マネージャーを使用したり、独自のゲームを作成したりしない方が簡単であることがわかりました。たとえば、私はカード ゲームと、カードがプレイされた場所を見て、それと現在のパネル サイズに基づいて配置するカスタム レイアウト マネージャーを持っています。

于 2010-11-25T19:37:06.820 に答える
0

この投稿でダリルの解決策 (最後の返信) を確認してください。それはトリッキーになり、「ボタン」を黒いボタンとして使用するため、白い「JButton」の上にペイントします。これは、AWT と Swing コンポーネントの混在を許可する新しいバージョンの JDK では機能しない可能性があります。

ただし、すばらしい点は、キーをクリックすると実際に音が発生することです。

于 2010-11-25T21:53:53.637 に答える