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

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

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

JFrameはJFC/Swingフレームワークのコンポーネントであり、トップレベルのコンテナです。

Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

Q&A

解決済

1回答

2159閲覧

ボタンを押しているときのみ動作するようにしたい

cretter

総合スコア91

JFrame

JFrameはJFC/Swingフレームワークのコンポーネントであり、トップレベルのコンテナです。

Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

0グッド

0クリップ

投稿2021/06/12 14:05

編集2021/06/13 06:18

前提・実現したいこと

矢印キーを押している間、画像が任意の方向に上下左右に動くプログラムを作っています。そこで初めは矢印キーを押した瞬間にすこし反応し、一瞬反応しなくなった後に連続で反応するようになっていました。しかし、初めに少し止まるのはあまりよくなかったので、次はwhile文を使ってFPS制御にし、矢印キーを押すと押した方向に進むメソッドを有効にする方法に変えました。しかし、それだと矢印キーを離しても動き続けてしまいました。なので次は、矢印キーを離したときに進むメソッドを無効にするようにしようとしていますが、これが最適なのでしょうか。教えてください。理想はマインクラフトやマリオなどのボタンから手を離した時に止まる動きです。

追伸:
画像はswingJFrameに色付きJPanelを表示しています。
矢印キーの読み込みはKeyListenerを使用しています。
サンプルコードは少し待ってください。

追伸:
ソースコードを追加しました。
ソースコード1が一番最初の案でソースコード2が一番新しいものです。

###ソースコード1

import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Test extends JFrame implements KeyListener{ final int SPEED=5; int x=50,y=50;//xとy座標 JPanel panel; public static void main(String[] args){ Test cl = new Test("Test"); } Test(String title){ setTitle(title); setSize(600,400); setLocationRelativeTo(null); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(null); panel = new JPanel(); panel.setBackground(Color.BLACK); panel.setBounds(x,y,50,50); add(panel); setVisible(true); addKeyListener(this);//KeyListener } @Override public void keyTyped(KeyEvent e){/*何かのキー(aなど)を押した場合の処理*/} @Override public void keyPressed(KeyEvent e){/*キーを入力した際の処理*/ switch(e.getKeyCode()){ case KeyEvent.VK_UP://上キー 上移動 y-=SPEED; break; case KeyEvent.VK_DOWN://下キー 下移動 y+=SPEED; break; case KeyEvent.VK_LEFT://左キー 左移動 x-=SPEED; break; case KeyEvent.VK_RIGHT://右キー 右移動 x+=SPEED; break; } panel.setBounds(x,y,50,50); } @Override public void keyReleased(KeyEvent e){/*キーを離した際の処理*/} }

###ソースコード2

import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Main{ public static void main(String[] args){ Test cl=new Test("Test"); try{ while(true){ long s_Time = System.currentTimeMillis();//計測開始 for(int i=0;i<4;i++){ cl.movePanel(i,cl.wsad[i]); } cl.repaint(); long e_Time = System.currentTimeMillis();//計測終了 //FPS制御 try{ Thread.sleep(1000/cl.FPS-(e_Time-s_Time)); }catch(Exception e){ System.out.println("<Error>"+cl.FPS+"FPSの許容範囲を超えています ["+(1000/cl.FPS-(e_Time-s_Time))+"ms必要]"); } } }catch(Exception ee){ ee.printStackTrace(); } } } class Test extends JFrame implements KeyListener{ final int SPEED=2; final int FPS=60; int x=50,y=50;//xとy座標 JPanel panel,ball; boolean[] wsad = new boolean[4]; Test(String title){ setTitle(title); setSize(600,400); setLocationRelativeTo(null); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(null); panel = new JPanel(); panel.setBackground(Color.BLACK); panel.setBounds(x,y,50,50); add(panel); setVisible(true); addKeyListener(this);//KeyListener } @Override public void keyTyped(KeyEvent e){/*何かのキー(aなど)を押した場合の処理*/} @Override public void keyPressed(KeyEvent e){/*キーを入力した際の処理*/ switch(e.getKeyCode()){ case KeyEvent.VK_UP://上キー 上移動 wsad[0]=true; break; case KeyEvent.VK_DOWN://下キー 下移動 wsad[1]=true; break; case KeyEvent.VK_LEFT://左キー 左移動 wsad[2]=true; break; case KeyEvent.VK_RIGHT://右キー 右移動 wsad[3]=true; break; } } @Override public void keyReleased(KeyEvent e){/*キーを離した際の処理*/ switch(e.getKeyCode()){ case KeyEvent.VK_UP://上キー 上移動 wsad[0]=false; break; case KeyEvent.VK_DOWN://下キー 下移動 wsad[1]=false; break; case KeyEvent.VK_LEFT://左キー 左移動 wsad[2]=false; break; case KeyEvent.VK_RIGHT://右キー 右移動 wsad[3]=false; break; } } void movePanel(int c,boolean go){ if(!go) return; int x,y; switch(c){ case 0: x=0; y=-1; break; case 1: x=0; y=1; break; case 2: x=-1; y=0; break; default: x=1; y=0; break; } this.x+=x*SPEED; this.y+=y*SPEED; panel.setLocation(this.x,this.y); } }

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

java version "16.0.1" 2021-04-20
Java(TM) SE Runtime Environment (build 16.0.1+9-24)
Java HotSpot(TM) 64-Bit Server VM (build 16.0.1+9-24, mixed mode, sharing)

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

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

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

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

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

hope_mucci

2021/06/12 14:38

現状の動作ができているソースコードを質問文中に編集で追加しましょう。 コードを見れば、問題点を指摘できる回答者が現れるかも。 コードは```と```で括りましょう。右側のプレビューもよく確認すること。
Yoshi88

2021/06/12 14:42

おそらく、キーバッファから読みっとっているからですね まずは、うまくいかなかったコードを載せたほうがいいですよ。きっと適格なアドバイスが受けれるようになります
guest

回答1

0

ベストアンサー

ソースコード2の方だけ見て回答します。

KeyPressedKyeReleasedイベントでキーの入力状態を制御しようとすると、キーを押下中にウィンドウフォーカスを失うとキーを離してもずっと移動しっぱなしの現象が発生します。
(矢印キーを押したままAlt+Tabで別のウィンドウに切り替えると簡単に再現します)

これを解消するのであれば、毎フレームごとにキーの押下状態を監視する方式へ変更したほうが良いかと思います。許容できるのであれば今のままでも良いかとは思います。(昔のゲームにはよくこういうことがありました)

あと、毎フレームごとのチェック処理をmainメソッド内に書かれていますが、これはJFrameクラス側に実装しなおすべきです。(テストであっても、これはどうかと思う)JFrame側で定期的に何かしらの処理を実行するのであれば、java.swing.Timerクラスを使ったActionListenerを実装してください。

投稿2021/06/13 11:18

hope_mucci

総合スコア4447

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

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

cretter

2021/06/13 13:10

>毎フレームごとにキーの押下状態を監視する方式 まさにこれが知りたかったです。`while`文の中に`get〇〇()`などで現在のキーの状況を知る方法を教えてください。
cretter

2021/06/13 13:15

>毎フレームごとのチェック処理 `JFrame`側に実装するときの注意点などありますか? ``` class Main{ public static void main(String[] args){ Test cl = new Test(); cl.running(); } } class Test extends JFrame{ void running(){ while(true){ //FPS制御 } } } ``` でもいいのでしょうか?
hope_mucci

2021/06/13 14:08

キーの入力状況はイベント以外で取得することはできないはずなので、監視処理の中でウィンドウがアクティブかどうかを取得(isActive())し、アクティブでなくなったらキー入力状況の配列を全部0にする、とするとその時点でオブジェクトの動きも停止させることができると思います。 また、上のコメントに書いたような無限ループはスレッドをロックする可能性があるので、Timerクラスのイベントを使った方がより安全であると思います。
cretter

2021/06/13 14:43

>アクティブでなくなったらキー入力状況の配列を全部0 素晴らしい案です。ありがとうございます。 >Timerクラスのイベントを使った方がより安全であると思います。 すみませんがTimerクラスを一度も使ったことがなくいろいろサイトを見たのですがなかなかFPS用のサンプルコードが見つからなかったので、例かそれが乗っているサイトまたはヒントを教えてください。
hope_mucci

2021/06/13 15:13

FPS用がどのような実装を差すのか理解できませんが、"java swing timer"で検索したら実装例はいくらでも出てきます。最低限公式リファレンスや老舗のサイトを熟読しましょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問