質問するログイン新規登録
Java

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

Q&A

解決済

2回答

345閲覧

mouseClickedイベントが発生しない(拾えない)場合が度々ある

t0.me_ji

総合スコア11

Java

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

1グッド

0クリップ

投稿2025/09/30 12:19

編集2025/09/30 13:39

1

0

実現したいこと

添付JavaプログラムでmouseClickedイベントを ”常に” 拾えるようにしたい。

前提

画面に表示された5x5のJLabelを次々にクリックし、mouseClickedイベントを拾ってJLabellの色を変更(白<->水色)したいのですが、イベントを拾えない場合がしばしば発生します。同じJLabelを繰り消しクリックすると拾えることが多いです。

該当のソースコード

java

1import java.awt.Color; 2import java.awt.Container; 3import java.awt.Dimension; 4import java.awt.event.MouseAdapter; 5import java.awt.event.MouseEvent; 6 7import javax.swing.BorderFactory; 8import javax.swing.JFrame; 9import javax.swing.JPanel; 10import javax.swing.JRootPane; 11import javax.swing.border.LineBorder; 12 13public class TEST extends JFrame { 14 //---------------------------------------------------------- 15 static public void main(String args[]) { new TEST(); } 16 //---------------------------------------------------------- 17 public TEST() { 18 19 JRootPane root = getRootPane(); 20 root.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.RED)); 21 setLocationRelativeTo(null); 22 setResizable(false); 23 24 JPanel p = new JPanel(); 25 p.setPreferredSize(new Dimension( 50*5, 50*5 )); 26 p.setLayout(null); 27 Container cp = getContentPane(); 28 cp.add(p); 29 30 for (int row=0; row<5; row++) for (int col=0; col<5; col++) 31 p.add(new Box(row, col)); 32 33 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 34 pack(); 35 setVisible(true); 36 } 37} 38//-------------------------------------------------------------- 39class Box extends JPanel { 40 int r, c; 41 Box(int row, int col) { 42 r = row; 43 c = col; 44 setBounds(50*c,50*r, 50,50); 45 setBorder(new LineBorder(Color.BLACK, 1, true)); 46 setBackground(Color.WHITE); 47 setLayout(null); 48 addMouseListener(new MyMouseAdapter()); 49 } 50 private class MyMouseAdapter extends MouseAdapter { 51 @Override 52 public void mouseClicked(MouseEvent e) { 53 System.out.println("mouseClicked "+(r+1)+"-"+(c+1)); 54 Color c = getBackground(); 55 setBackground(c==Color.WHITE ? Color.CYAN: Color.WHITE); 56 } 57 } 58}

試したこと

MouthAdapterではなくMouseListenerでも同じ現象でした。

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

jdk21 windows-x64_bin.exeをインストール
Eclipse 2025上で開発

TN8001😄を押しています

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

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

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

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

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

jimbe

2025/09/30 12:43

コードは「コードのマークダウン」を用いてご提示ください。でないと、コードの一部が文字修飾等のマークダウンとされて消えてしまう場合があります。 具体的には、コードを 「```java」の行と「```」 の行で挟んでください。
jimbe

2025/09/30 12:58

「イベントを拾えない」とはどのように判断されたのでしょうか。
t0.me_ji

2025/09/30 13:50

MyMouseAdapterの mouseClicked()が呼ばれれば、Eclipseのコンソールに System.out.println("mouseClicked "+(r+1)+"-"+(c+1)); の結果が表示されるのですが、されないことで確認しました。 rとc は5行5列のBoxのどれがクリックされたかを表しています。また、イベントが拾えれば、画面上のBoxの色が変化しますが、変化しません。 イベントを拾える・拾えないは、画面上の5x5のBoxを連続的にクリックすると、両方の場合が混在して現れます。
guest

回答2

0

画面に表示された5x5のJLabelを次々にクリックし、mouseClickedイベントを拾ってJLabellの色を変更(白<->水色)したいのですが、イベントを拾えない場合がしばしば発生します。

こちらの手元(Windows11)では急いでクリックしようとして、mousePressedmouseReleasedの間にマウスが動くとmouseClicked判定にはなりませんでした。
[JDK-4218549] an allowable "smudge factor" for all mouse clicks - Java Bug System

アプリ動画


マウスが動いても良いようにするなら、JToggleButtonベースにしたらいかがでしょうか。

java

1import javax.swing.*; 2import java.awt.Color; 3import java.awt.Dimension; 4 5public class TEST extends JFrame { 6 static void main(String[] args) { 7 new TEST().setVisible(true); 8 } 9 10 TEST() { 11 getRootPane().setBorder(BorderFactory.createLineBorder(Color.RED)); 12 13 var p = new JPanel(null); 14 p.setPreferredSize(new Dimension(50 * 5, 50 * 5)); 15 add(p); 16 17 for (var row = 0; row < 5; row++) 18 for (var col = 0; col < 5; col++) 19 p.add(new Cell(row, col)); 20 21 pack(); 22 23 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 24 setLocationRelativeTo(null); 25 setResizable(false); 26 } 27} 28 29class Cell extends JToggleButton { 30 Cell(int row, int col) { 31 setBounds(50 * col, 50 * row, 50, 50); 32 setBorder(BorderFactory.createLineBorder(Color.BLACK, 1, true)); 33 setBackground(Color.WHITE); 34 addActionListener(e -> { 35 System.out.println("Clicked " + (row + 1) + "-" + (col + 1)); 36 setBackground(getBackground() == Color.WHITE ? Color.CYAN : Color.WHITE); 37 }); 38 39 // [java - Changing the background color of a selected JToggleButton - Stack Overflow](https://stackoverflow.com/questions/5808022) 40 setContentAreaFilled(false); 41 setOpaque(true); 42 } 43}

アプリ動画


Boxクラスはすでにあるので他の名前がいいでしょう。
Box (Java SE 21 & JDK 21)

投稿2025/09/30 14:21

編集2025/10/02 05:03
TN8001

総合スコア10208

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

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

TN8001

2025/09/30 14:22

解決されたようですが^^;
t0.me_ji

2025/10/02 00:41

回答、ありがとうございます。 ご指摘のように「mousePressed・mouseReleasedの間にマウスが動くとmouseClicked判定にはなりません」というのが問題の根本原因だったようです。マウスイベントは「そういう仕組みである」というのは、JDKの説明書のどこかに記載されてるのでしょうか?それとも経験則で判明した事実なのでしょうか? 私としては、当面の問題が解決できればいいので、jimbeさんのご指摘に従ってmouseClickedからmousePressedに処理を移して問題は解決しました。 なお、JPanelではなくJToggleButtonにする案は参考になります。ただ、今回の質問は、より大がかりなアプリの一部を切り出して質問しているのですが、アプリの構造上、JPanelを使わざるを得ない事情があって採用できません。 また、Boxというクラス名は既存クラスとバッティングするので別名にすべしとのご指摘は今後気をつけます。現状はBoxという名称をアプリのいたる所で使っていて改名箇所が大量になるので、このままの名称で通します。
TN8001

2025/10/02 04:54

> マウスイベントは「そういう仕組みである」というのは、JDKの説明書のどこかに記載されてるのでしょうか?それとも経験則で判明した事実なのでしょうか? わたしは動画のようにやってみて気が付きました。 ただ一般的にはドラッグ閾値未満の移動は、無視すべきと思いますね。 どうやらこれはバグのようです。 [[JDK-4218549] an allowable "smudge factor" for all mouse clicks - Java Bug System](https://bugs.openjdk.org/browse/JDK-4218549) > mouseClickedからmousePressedに処理を移して問題は解決しました。 mousePressedで早すぎないならそれで十分でしょう^^ mouseReleasedのタイミングのほうが好ましいなら、ひと手間いりますね^^;
t0.me_ji

2025/10/02 08:18

TN8001さん、情報、ありがとうございます。 pressedとreleasedの間に1ピクセルでも動くsmudgeがあるとclickedとは見做さないという厳格さが妥当かどうかが1999年から問題になってたんですね。 最新のJDKでも「妥当」とされてるのか、あるいは、「つまらないことでツベコベ言うな」として無視されてきたのかは知る由もありませんが、現状が「仕様」なら、そういうふうになっていて、smudgeは1ピクセルたりとも許容しない、ということを mouseClicked()メソッドの説明に書いて欲しいものです。現状は「コンポーネント上でマウス・ボタンをクリック(押してから離す)したときに呼び出されます」としか書いていません。 個人的意見ですが、 案1: mouseClicked()は紛らわしいので廃止 案2: mouseReleased()の直後に、無条件にmouseClicked()を呼び出す    → released座標=clicked座標 案3: smudgeがあるとmouseClicked()は呼ばれない旨、目につく所に明記 のどれかが良さそうに思います。smudgeを許容する案は賛成できません。
t0.me_ji

2025/10/02 08:29

長文コメントを投稿したらエラーになって、変な切り貼りされてしまいました。 5行目以降は、個人的には、次の3案のどれかにしてもらえるといいと思うと書きました。 案1: mouseClickedは紛らわしいので廃止 案2: mouseReleaseed直後にmouseClickedを発生(relese座標=click座標) 案3: smudgeは許容しないことをmouseClickedの説明に明記
t0.me_ji

2025/10/02 08:32

投稿システムがおかしい。文章の文字数制限がある???
TN8001

2025/10/02 09:37 編集

> 最新のJDKでも「妥当」とされてるのか、あるいは、「つまらないことでツベコベ言うな」として無視されてきたのかは知る由もありませんが、 クローズ理由は私には読み取れませんが、何にしろ今更手が入るとも思えませんね... ドキュメントの修正ぐらいならあり得るかな?(その辺の手続きどうするのか知りませんが^^; > 長文コメントを投稿したらエラーになって、変な切り貼りされてしまいました。 コメントも編集できます。コメントにマウスを乗せると右上に「…」が出るので、クリックして編集を選んでください^^ > 投稿システムがおかしい。文章の文字数制限がある??? 質問や回答は1万文字制限だと思います。 コメントの文字数はどうなんだろう?少なくとも数千文字書いてるコメントも見たことあります。 編集してみて同様だったら、メンテナンスで制限が付いた可能性はあります(あるいはバグか^^;
t0.me_ji

2025/10/04 11:01

返信ありがとうございます。 いちアジア人が「こうあるべき」と言ったところで、仕様が変るとは思えないので、言うだけ無駄でした。とにかく、やりたいことがやれるようになったので、これでオシマイにします。お付き合い、ありがとうございました。
guest

0

ベストアンサー

基本的には、"本当に" イベントが拾えないのなら処理速度のような要因でしょうからそれは仕方ないことと思います。イベントが来たら処理するというしかないでしょう。(ちなみにコンソールへの表示は案外重いです。)

が、イベントが拾えてない "ように見える" ということはありそうです。
setBackground の実行は、必ずしも再表示はしてくれません。 setBackground したらそのパネルの repaint を呼んでみては如何でしょうか。

他に、クリックと判断するには時間が必要な為、クリックでは無くプレスで処理(色変え)するというテもあるかもしれません。

ついでに、 setLocationRelativeTo を使って真ん中に表示するなら、 pack の後にした方が良いです。
setLocationRelativeTo はその時点でのサイズで真ん中を決めますので、後から pack してもウインドウの大きさで中央が合いません。

投稿2025/09/30 13:24

編集2025/09/30 13:38
jimbe

総合スコア13422

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

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

t0.me_ji

2025/09/30 14:11

回答ありがとうございます。 mousePressed()に変更したところ。毎回拾えるようになりました。 setBackground()直後のrepaint()は特に効果がありませんでした。 setLocationRelativeToをpack()後にするご提案は別途、試してみます。 今のところ、そうしなくても特に問題は無いので。
t0.me_ji

2025/09/30 14:14

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問