質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.33%

javaでのkey入力によるbutton点滅方法について。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,291

score 20

実現したいこと

javaでキーを入力した時に音がなるゲームを作ろうと思っています。
音を出すこと自体は成功しているのですが音を出したボタンを点滅させたい
とおもい(キーが押されたことを表現したく)やってみたのですが該当するようなコードが調べても出てきません。キーを押した時に該当するボタンを点滅させたいです。
どなたか可能な方はいらっしゃいますでしょうか。よろしくお願い致します。

該当のソースコード

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;

import java.awt.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
import java.util.*;

import java.applet.*;

import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;

class RoundButton extends JButton {//画像の背景を透過させるクラス
//-----------------------------------------------------
class Controller extends WindowAdapter  implements KeyListener{     //キー入力を判別するクラス
//----------------------------------------------------

class Model extends Observable{
private AudioClip pong;
public void snea1(){ //音を鳴らす
}
//-----------------------------------------------------

class View4 extends JFrame{

public View4(Controller aController){

this.setSize(750,440);

JPanel p =new JPanel();

p.setLayout(null);

ImageIcon icon1 = new ImageIcon("画像ファイル");

RoundButton snea1=new RoundButton(icon1);

snea1.setBounds(50, 250, 150, 150);//位置と大きさ

p.setOpaque(false);

snea1.addKeyListener(aController);

snea1.setActionCommand("snea1");

p.add(snea1);

this.setFocusable(true);

this.addWindowListener(aController);
getContentPane().add(p, BorderLayout.CENTER);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args){
new View4(new Controller(new Model()));
}
}

補足情報(言語/FW/ツール等のバージョンなど)

このプログラムはmvcモデルで作成しています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KSwordOfHaste

    2016/12/15 19:20 編集

    コードは<code>ボタンを使って適切に字下げしてください。

    キャンセル

  • datuota00

    2016/12/16 01:28

    <code>はそういう風に使うのですね。自分の勉強不足でみにくくなってしまいました。すいません。ご指摘ありがとうございます。よろしければコメントの疑問、考えていただけると幸いです。失礼いたしました。

    キャンセル

  • KSwordOfHaste

    2016/12/16 09:57

    質問がクローズ状態になってしまってますが、それでも後から閲覧するひとのために質問を編集しておくことが望ましいですよ。

    キャンセル

  • datuota00

    2016/12/16 11:35

    見辛くなってしまうのでまた新しい質問としてあげさせていただきます。 こういうのははじめてでいろいろ教えていただきありがとうございます。

    キャンセル

回答 1

checkベストアンサー

0

javax.swing.Timerを使うのがよいと思います。一定時間ごとにActionEventを通知してくれるのでそのハンドラーでボタンの明滅処理などを行えばよさそうです。TimerによるイベントはEvent Dispatch Thread上でハンドラーが起動されるのでスレッド間の同期などはとりあえずは気にする必要はありません。

コントローラーのKeyTypedハンドラーでイベント発行元のボタンを明滅するコード例は以下のような感じです。点滅処理はいい加減なのでそこは読み替えてください。

class Controller extends WindowAdapter  implements KeyListener {
    ...
    Timer timer;
    RoundButton flushButton;
    Color defaultColor = Color.GRAY; //色は適当です
    Color flushColor = Color.RED; //色は適当です
    boolean flushFlag;

    Controller(Model model) {
        ...
        timer = new Timer(1000, this::expired); // 1秒ごとにexpiredを起動
        timer.setRepeats(true);
    }

    //ボタンの点滅を開始
    void flushButton(RoundButton button) {
        timer.stop();
        if (flushButton != null) {
            // 以前点滅していた別のボタンの色をデフォルトに戻す
            flushButton.setBackground(defaultColor);
        }
        flushButton = button;
        timer.start();
    }

    //ボタンの点滅(Timerにより起動)
    void expired(ActionEvent ev) {
        flushFlag = !flushFlag;
        flushButton.setBackground(flushFlag ? defaultColor : flushColor);
        flushButton.repaint();
    }

    @Override
    public void keyTyped(KeyEvent e) {
        ...
        if (e.getSource() instanceof JButton) {
            flushButton((JButton)e.getSource());
        }
    }
    ...
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/16 01:22

    class Controller extends WindowAdapter implements KeyListener{
    private Model model;
    Timer timer;
    RoundButton flushButton;
    Color defaultColor = Color.GRAY;
    Color flushColor = Color.RED;
    boolean flushFlag;
    public Controller(Model model){
    this.model=model;
    timer = new Timer(1000, this::expired);
    timer.setRepeats(true);
    }

    public void keyTyped(KeyEvent actionEvent){
    char c= actionEvent.getKeyChar();
    switch(c){
    case'a': model.snea1(); break;
    case'q': model.symbal2(); break;
    case'f': model.tam1(); break;
    case'g': model.tam2(); break;
    case'h': model.tam3(); break;
    case'b': model.bass(); break;
    case'p': model.crush(); break;
    case'l': model.hihat(); break;
    }

    if (actionEvent.getSource() instanceof RoundButton) {
    flushButton((RoundButton)actionEvent.getSource());
    }

    }
    public void keyPressed(KeyEvent actionEvent){ }
    public void keyReleased(KeyEvent actionEvent){ }

    public void flushButton(RoundButton button) {
    timer.stop();
    if (flushButton != null) {
    flushButton.setBackground(defaultColor);
    }
    flushButton = button;
    timer.start();
    }

    void expired(ActionEvent ev) {
    flushFlag = !flushFlag;
    flushButton.setBackground(flushFlag ? defaultColor : flushColor);
    flushButton.repaint();
    }

    }

    ご回答本当にありがとうございます。
    教えていただいたコードを書き込んで繋がるように少しいじってみましたが、コンパイルしたところ、点滅はせず画像に変化がありませんでした、、
    上記がcontrollerクラスです。自分なりに考えた結果 void expired(ActionEvent ev)がちゃんと機能していないのではないかと思いました。お時間ございましたらご意見お聞かせください。宜しくお願い致します。

    キャンセル

  • 2016/12/16 09:42

    質問コメントにも書きましたがコードは整形(字下げ)して閲覧者に見やすくすることが重要です。全ての質問は同様の疑問を持つ全ての閲覧者で共有することが望ましいからです。コメントでは字下げができませんので長いコードは質問文を編集するすることによって記載するようにしてくださいね。

    キャンセル

  • 2016/12/16 09:45

    失礼、本質問はベストアンサーがつけられてしまってるので「解決済み」になってしまってます。ベストアンサーを外して未解決にもどせるのかな?もし戻せないなら新たな質問を起こした方がよいですね。

    キャンセル

  • 2016/12/16 11:40

    ちなみに自分は一応コードを動かしてみて点滅を確認しました。キーイベントが発生するためにはフォーカスがRoundButtonになければならないことや、RoundButtonのbackgroundを変えることが本当に点滅になってくれるのかはなんともいえません。expiredが起動しているかはデバッグプリントで確認できますが、backgroundを変えたときの効果がどうなるかはRoundButtonの実装をみないとなんともいえません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る