多くのサイトを見て、色々考えているのですが、イマイチ理解が及びません。以下のような風に思っていていいのでしょうか。
・Swingではメインとなるmainスレッド(表現は正しくないかもしれない)と、描画関係のイベントを実行するイベントディスパッチスレッドで出来てる。
・描画関係のイベント(正確にはコンポーネントの可視化及び可視化したコンポーネントの描画)はイベントディスパッチスレッド上で実行しなければならない。
・SwingUtilities.invokeLaterを使うことによってその中身のプログラムをイベントディスパッチスレッドで実行してくれる...?
→setVisible(true)やsetText("")など全てSwingUtilities.invokeLaterを使って記述しなければならない.....???(面倒すぎじゃないでしょうか)
・Swingでのマルチスレッドを行うにはSwingWorkerを使う(ことは見つけているのですが、まずEDTについて理解しないと先に進めないと思い、まだあまりこれの内容は調べていません)
・描画系の命令を実行しないのならば、別スレッドを作成して使用しても良い....?
こんなところでしょうか。
しかし、このとおりだとすると今までの自分の書いてきたプログラムは間違いだらけ(特に「全ての描画系命令をSwingUtilities.invokeLaterを使いEDTで実行する」点)になってしまいます。
ちゃんとした理解をしておきたいので、わかりやすい説明でも、上記の間違っている点でもご教示願います。
A 回答 (1件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
書いてあること自体は、一部を除いて、ほぼ間違っていないと思います。
ただ、自分の書いたコードがイベントディスパッチスレッドで動いているのかそうでないのか、よくわからなくて混乱されているような印象を持ちました。
Swingは、シングルスレッドの設計です。Swingコンポーネントに対する呼び出しは、イベントディスパッチスレッド(EDT)上で行われる必要があります。例外は、repaint()です。
マウス、キーボード操作などのイベントも、すべてEDT上で処理します。
アプリケーションの処理はイベントに対する反応として記述します。これが、イベント発生時に呼び出されます。イベントは1つのスレッド上で順番に処理されます。
こういう設計は、イベント駆動といって、プラットフォームを問わず、GUIを持つアプリケーション用の仕組みとして一般に見られるものです。
http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%99% …
> Swingではメインとなるmainスレッド(表現は正しくないかもしれない)と、描画関係のイベントを実行するイベントディスパッチスレッドで出来てる。
Javaでmainスレッドというと、最初に作られるスレッドですが、mainスレッド自体はとくに必要無いので、終わってしまってもかまいません。実際、自分の作ったアプリケーションでも、用が済んだらmainスレッドはすぐに終了してしまいます。EDTが重要です。
ただ、シングルスレッドの設計とはいえ、Swingは、EDT以外のスレッドも内部で使用します。
例えば、java.awt.Toolkitで画像を読み込むとバックグラウンドのスレッドで読み込まれます。
画像の読み込みには一般的に時間がかかるからです。
> 描画関係のイベント(正確にはコンポーネントの可視化及び可視化したコンポーネントの描画)はイベントディスパッチスレッド上で実行しなければならない。
そうです。描画というより、Swingコンポーネント関係の操作をEDT上で行う必要があります。
コンポーネントの描画もEDT上で行われます。
可視化というのが何を指すのか、ちょっと意味がとれませんでしたが…
setVisible(true) のことでしょうか? ということなら、これもその通りです。
> SwingUtilities.invokeLaterを使うことによってその中身のプログラムをイベントディスパッチスレッドで実行してくれる...?
そうです。invokeLaterに渡したRunnableオブジェクトのrunメソッドを呼ぶというイベントが、イベントキューに入れられます。イベントが処理されるとrunメソッドが呼ばれます。
そのため、即座に実行されるわけではなく、実行が予約されるような動きであると思ってください。
> →setVisible(true)やsetText("")など全てSwingUtilities.invokeLaterを使って記述しなければならない.....???(面倒すぎじゃないでしょうか)
EDT以外から、setText等のSwingコンポーネントの操作をしたいのならその通りです。
しかし、マウス、キーボードイベントのようなイベント処理はそもそもEDT上で動くわけですから、そこでsetText等をする分には、invokeLaterを使っていなくても問題ないです。
そういう意味では、「全て」ではありません。あくまで、EDT以外のスレッドからの場合です。
> 面倒すぎじゃないでしょうか
すべてマルチスレッドで同期をきちんと考える面倒さと、全部をEDTでやる面倒さ、どっちが面倒か、ですね。
自分としては、用もないのにマルチスレッドで処理したくはありません。
マルチスレッドで、破綻無く動かすのはなかなか面倒です。
SwingWorkerについてですが、長時間の処理を実行したいとき、EDTで処理してしまうとイベントディスパッチループへ処理を返さないことになり、他のイベントを処理できなくなります。画面は固まって、応答なしになります。
となると、重い処理は別のスレッド(作業用スレッド)で実行したくなります。問題は画面へのアクセスです。プログレスバーのように、処理中の状況を画面に表示したいことがあると思います。しかし、EDT以外のスレッドからSwingコンポーネントにはアクセスできません。描画処理はイベントを送ってEDT側で処理する必要があります。
SwingWorkerは、この手の作業用スレッドとEDTとのやりとりや、作業スレッドの再利用など、面倒なところを助けてくれるものです。
便利ですが、使わなければいけないというわけではありません。ルールを守っていれば、自分で同じような仕組みを書けばいいので。でも、便利なので使いますけど。
> 描画系の命令を実行しないのならば、別スレッドを作成して使用しても良い....?
もちろんです。問題になるのは、描画系というかSwingコンポーネント関係です。
ただし、結果を表示したいとなったら、EDTに頼む必要があります。
見えないSwingの中でやっていることがいろいろあるので、なかなか、何がどこのスレッドで、どういうタイミングで動くのかイメージするのが難しいかもしれません。
細かく丁寧にありがとうございます。おかげで私の中で大きく勘違いをしていることに気づくことができました!!
今まで私はソースコードとして書いたプログラムをどのスレッドが行っているのか把握していませんでした。イベントリスナーによって実行されるプログラムなどはメインスレッドが行っているものだと思っていました。そのため理解に苦労していたのだと思います。
詳しい説明をありがとうございました! これからはSwingのスレッドポリシーに則ってプログラムを書こうと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・ことしの初夢、何だった?
- ・【お題】大変な警告
- ・【大喜利】【投稿~1/20】 追い込まれた犯人が咄嗟に言った一言とは?
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・【お題】逆襲の桃太郎
- ・自分独自の健康法はある?
- ・最強の防寒、あったか術を教えてください!
- ・【大喜利】【投稿~1/9】 忍者がやってるYouTubeが炎上してしまった理由
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Java、jPanelに描画する
-
JAVAでの背景画像表示
-
VB.NETのSendMessageを教えてく...
-
Javaアプレットで描画の中断が...
-
JavaScriptで直線を描画したい
-
GDI+で描画した画像を消去する...
-
VB.NET フォーム上に描いたグ...
-
C# DataGridView のCellPaintin...
-
JavaでのDirectXの使用
-
アクセスで他アプリから復帰し...
-
SwingとEDT(イベントディスパッ...
-
C# リストビューの特定のセルの...
-
C#のGraphicsクラスについてです。
-
OpenLayersの描画を固定で表示...
-
度々すいません、Javaについて...
-
「タイプ初期化子が例外をスロ...
-
private static という変数の修飾
-
エクセルVBAで、条件に一致する...
-
変数名の付け方
-
オブジェクト参照がオブジェク...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VB.NETのSendMessageを教えてく...
-
VB.NET フォーム上に描いたグ...
-
Canvas等の図形を移動する時,直...
-
Androidで画像の中で指定した範...
-
JAVAでの背景画像表示
-
C# DataGridView のCellPaintin...
-
画面のちらつきの原因が知りた...
-
Java 15パズルを作ったのですが...
-
SwingとEDT(イベントディスパッ...
-
重なった要素上でのイベントで...
-
Java Script 色を塗れるプログ...
-
GDI+で描画した画像を消去する...
-
ドラッグして矩形を描くには
-
Javaで文字の角度を変えて表示...
-
音声再生/SourceDataLineの遅延
-
最接近点を持つ線を特定
-
BMP画像を画像処理して連続に表...
-
canvasで表示されてる画像を1...
-
C#のGraphicsクラスについてです。
-
Java、jPanelに描画する
おすすめ情報