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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

2646閲覧

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

datuota00

総合スコア20

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/12/16 02:55

編集2016/12/16 06:16

###疑問、問題
前回の質問でいろいろしったのでまた新しく質問を書きなおさせていただきます。また、コードを全文のせた方がいいとのご指摘もあったのでそうさせていただきます。
問題ですが、Controller classにおいて追加させていただいたtimerがうまく機能せず点滅させることができない状況です。キーボードから該当のボタンへの入力があった際それがあったとわかるように画像を変化させたい、今回その一つとして点滅をえらびました。どこが原因で噛み合わないのか見当がつかないのですがわかる方はいらっしゃいますでしょうか。どうぞよろしくお願い致します。
###ソースコード

import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowAdapter; import javax.swing.Timer; 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 {//ボタンに貼り付けた画像の一部を透過させるクラス(ここは問題ないはずです) protected Shape shape; protected Shape base; public RoundButton(Icon icon){ super(icon); setModel(new DefaultButtonModel()); setBackground(Color.BLACK); setContentAreaFilled(false); setFocusPainted(false); setBorderPainted(false); setAlignmentY(Component.TOP_ALIGNMENT); initShape(); } protected void initShape(){ if(!getBounds().equals(base)){ Dimension s = getPreferredSize(); base = getBounds(); shape = new Ellipse2D.Float(0,0,s.width,s.height); } } @Override public Dimension getPreferredSize(){ Icon icon = getIcon(); Insets i = getInsets(); int iw = Math.max(icon.getIconWidth(), icon.getIconHeight()); return new Dimension(iw+i.right+i.left,iw+i.top+i.bottom); } @Override public boolean contains(int x,int y){ initShape(); return super.contains(x,y); } } //------------------------------------------------------ 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/*actionEventでもだめだした*/) { flushFlag = !flushFlag; flushButton.setBackground(flushFlag ? defaultColor : flushColor); flushButton.repaint(); } } //---------------------------------------------------------------------- class Model extends Observable{//mvcにおけるmodelclass private AudioClip pong; public void snea1(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void symbal2(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void tam1(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void tam2(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void tam3(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void bass(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void crush(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } public void hihat(){ pong = Applet.newAudioClip(getClass().getResource("音声ファイル")); pong.play(); } } //--------------------------------------------------------- class View5 extends JFrame{//mvcにおけるviewclass public View5(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); ImageIcon icon2 = new ImageIcon("画像ファイル"); RoundButton symbal2=new RoundButton(icon2); symbal2.setBounds(0, 0, 180, 180); ImageIcon icon3 = new ImageIcon("画像ファイル"); RoundButton tam1=new RoundButton(icon3); tam1.setBounds(180, 100, 130,130); ImageIcon icon4 = new ImageIcon("画像ファイル"); RoundButton tam2=new RoundButton(icon4); tam2.setBounds(310, 50, 130,130); ImageIcon icon5 = new ImageIcon("画像ファイル"); RoundButton tam3=new RoundButton(icon5); tam3.setBounds(440, 100, 130, 130); ImageIcon icon6 = new ImageIcon("画像ファイル"); RoundButton bass=new RoundButton(icon6); bass.setBounds(285, 230, 180, 180); ImageIcon icon7 = new ImageIcon("画像ファイル"); RoundButton crush=new RoundButton(icon7); crush.setBounds(570, 0, 180, 180); ImageIcon icon8 = new ImageIcon("画像ファイル"); RoundButton hihat=new RoundButton(icon8); hihat.setBounds(500, 230, 180, 180); p.setOpaque(false); snea1.addKeyListener(aController); symbal2.addKeyListener(aController); tam1.addKeyListener(aController); tam2.addKeyListener(aController); tam3.addKeyListener(aController); bass.addKeyListener(aController); crush.addKeyListener(aController); hihat.addKeyListener(aController); snea1.setActionCommand("snea1"); symbal2.setActionCommand("symbal2"); tam1.setActionCommand("tam1"); tam2.setActionCommand("tam2"); tam3.setActionCommand("tam3"); bass.setActionCommand("bass"); crush.setActionCommand("crush"); hihat.setActionCommand("hihat"); p.add(snea1); p.add(symbal2); p.add(tam1); p.add(tam2); p.add(tam3); p.add(bass); p.add(crush); p.add(hihat); 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 View5(new Controller(new Model())); } }

上のプログラムはmvcモデルで構築しています。

###追加の質問

timer = new Timer(1000,this::expired);

のところですが、調べてみて"::"の使い方は理解できたのですが、コンパイルがここだけできないです。エラー文は

View5.java:63: エラー: ')'がありません timer = new Timer(1000,this::expired); ^ View5.java:63: エラー: 式の開始が不正です timer = new Timer(1000,this::expired); ^ View5.java:63: エラー: ';'がありません timer = new Timer(1000,this::expired);

となっています。javaのバージョンの問題でしょうか。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

  • setContentAreaFilled(false)

falseを指定すると「再描画の際に自動的に背景が塗りつぶされない」ので再描画を行うためのメソッド(JComponent#paintComponentなど)をoverrideして背景をも含めて明示的に描画する必要があります。
今のままではRoundButtonの「背景色をBLACKに初期化する」ことや「背景色変える」ことは描画結果には反映されません。ひとまずこの行をコメントアウトしてみてください。

  • KeyEventの設定について

前の質問のサンプルコード自体がイマイチだったですね・・・キー入力はフォーカスがあるコンポーネントに対して発生するものなので押下したキーに応じて点滅させたいボタンを変えるならKeyEvent#getSourceでボタンを知るのではなくキーコードから点滅させるべきボタンを切り分ける必要があると思います。

自分なら次のようにします。

java

1class View5 extends JFrame{ 2 //各ボタンをフィールドにしてControllerからアクセスできるようにする 3 RoundButton snea1; 4 RoundButton symbal2; 5 ... 6 public View5(Controller aController){ 7 aController.setView(this); // Controllerにビューインスタンスを教える 8 ... 9 ImageIcon icon1 = new XImageIcon("画像ファイル"); 10 snea1 = new RoundButton(icon1); // ボタンを初期化(ローカル変数ではなくフィールドに覚える) 11 ... 12 // ContentPaneであるJPanelでキーイベントを受けられるようにしておく(必ずしも必要ない) 13 p.setFocusable(true); 14 p.addKeyListener(this); 15 } 16} 17 18class Controller extends WindowAdapter implements KeyListener { 19 private Model model; 20 private View5 view; 21 ... 22 Color defaultColor = Color.BLACK;//ボタンのデフォルト背景色は黒なのでそれに合わせましょう 23 ... 24 //ControllerにViewインスタンスを覚えさせるメソッドを用意してやります 25 //MVC的にいやと思う向きもあるかも知れませんが自分はMVC的にこれやっても一向にかまわないと思います 26 public void setView(View5 view) { 27 this.view = view; 28 } 29 30 public void keyTyped(KeyEvent actionEvent){ 31 char c= actionEvent.getKeyChar(); 32 RoundButton button = null; 33 switch(c){ 34 case'a': model.snea1(); button = view.snea1; break; 35 case'q': model.symbal2(); button = view.symbal2; break; 36 ... 37 } 38 if (button != null) { 39 flushButton(button); 40 } 41// if (actionEvent.getSource() instanceof RoundButton) { 42// flushButton((RoundButton)actionEvent.getSource()); 43// } 44 } 45 46 //おまけ:JFrameがアクティベートされたとき、フォーカスをcontentPaneに移す 47 // contentPaneでキーを受けるつもりがないなら特定のボタンにフォーカスを移動してもよい 48 @Override 49 public void windowActivated(WindowEvent e) { 50 super.windowActivated(e); 51 // JPanelにフォーカスを設定するならこのように... 52 JPanel p = (JPanel)((JFrame)e.getSource()).getContentPane(); 53 p.requestFocus(); 54 // 特定のボタンにフォーカスを設定するならこのように.. 55 view.snea1.requestFocus(); 56 } 57}
  • 点滅のコードについて

キーを押したら即座に背景色を変更したほうがこのアプリケーションには合っていると思います。点滅感覚も1秒よりもっと短くしたほうがよさそうですね。そこはご自由にどうぞ。

java

1public void flushButton(RoundButton button) { 2 timer.stop(); 3 if (flushButton != null) { 4 flushButton.setBackground(defaultColor); 5 flushButton.repaint(); //これを入れておいた方がいいかもしれない。 6 } 7 flushButton = button; 8 timer.start(); 9 flushFlag = false; 10 expiared(null);//引数のnullはイマイチですが・・・ 11} 12 13void expired(ActionEvent dummy/*この引数はnullかもしれないので参照しちゃだめ*/) { 14 flushFlag = !flushFlag; 15 // flushFlagがtrueの場合にflushColorで描画としたほうが自然 16 flushButton.setBackground(flushFlag ? flushColor : defaultColor); 17 flushButton.repaint(); 18}
  • flush

点滅はflashでした。サンプルコードのflushは綴りミスです。お恥ずかしい限りです。


追記:
this::expiredはJava1.8以降で使えるメソッド参照構文というものです。1.7以前であれば次のようにするとよいと思います。

java

1//java1.8以降 2timer = new Timer(1000, this::expired); 3//java1.7以前 4timer = new Timer(1000, new ActionListener() { 5 @Override 6 public void actionPerformed(ActionEvent ev) { 7 expired(ev); 8 } 9}); 10

Controllerをimplements ActionListenerとしてexpiredメソッドをactionPerformedに置き換え、new Timer(1000, this);としてもよいのですがControllerはいろんなイベントをハンドリングする役割を持っているので上記のようにしたほうが柔軟だと思います。つまり色々な違う意味のActionEventを同一クラス内の複数のメソッドでそれぞれハンドリングできる仕組みとして設計したほうが柔軟だと思います。

投稿2016/12/16 05:42

編集2016/12/16 06:37
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

datuota00

2016/12/16 06:20

何回にもわたりご解答下さりまして本当にありがとうございます。とても勉強になります。またこのアプリケーションにおいてのこちらの意図まで汲んで下さり本当になんといえば。ありがとうございます。 ところで、少し疑問が増えてしまったので質問を修正させていただきました。よろしければご教授おねがいいたします。
KSwordOfHaste

2016/12/16 06:41 編集

本来は追加の疑問は別質問にしたほうがよいのですが、回答したコードを動かすらために必要な問題なので許容範囲だと思いました。回答は追記しておきました。質問の際にはこういったことが起きないように「前提バージョン」などを最初から記載しておくことをお勧めします。(ちなみにあなたがjava1.8をインストールしてあっても環境によってはエラーとなる可能性もあります。もしそうならインストールしている全てのjavaのバージョンやIDEの種類なども明記して改めて質問をおこしたほうがよいかもしれません)
datuota00

2016/12/18 11:17

難しいコードが多く、初心者の自分では読み解くのには時間がかかると思いますけれどもこれから勉強していきたいと思います。ご回答ありがとうございました!
KSwordOfHaste

2016/12/18 11:37

(大雑把にいうと)単一のメソッドだけを持つインターフェースが引数のとき、質問者さんのコードにあるように(A)「そのインターフェースを実装したクラスのインスタンスを指定する」、自分の追記にあるJava1.7以前に書いた方法(B)「無名クラス」、Java1.8の(C)「lambda記法」、Java1.8の(D)「メソッド参照」の4つの方法があります。(A)は大丈夫と思いますので、(B),(C),(D)の順番に「だんだん便利な書き方を学んでいく」のが良いと思いますよ!
KSwordOfHaste

2016/12/18 12:37

コードに間違いがありました。新たに質問をおこされたようなのでそちらで回答します。すみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問