Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

JMenuとJPanelを同時に使えません。

はじめまして。
質問したいのですが…

今、とあるアプリケーションを作っています。
MainFrame : JFrameをextends、Runnableをimplements
MyPanel   : JPanelをextends

MainFrameにMyPanelを貼り付け、
MainFrameのrun()の中にwhileループを作って定期的にMyPanelのインスタンスを更新しています。

で、MainFrameにJMenuBarでつくったメニューを付けました。

メニュー単体、パネル単体だとちゃんとできているのですが、両方一緒だとうまくいきません。
メニューをクリックすると、メニューアイテムが出てくるのですが、その上からパネルが上書きしてしまうようなのです。

__________________
| メニュー   |
 ----------------
| |アイテム|     |
| |アイテム|     |アイテムが出てくると
|  ̄ ̄ ̄ ̄ ̄     |
|                |
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
__________________
|メニュー    |
 ----------------
|                |
|パネル          |上からパネルが上書きする。
|                |
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

それで、パネルを更新するフラグを作って、
メニュー選択の間パネルを更新しないようにしようと思いました。

JMenuBarの、isSelected()というメソッドが、Menuを選択している間TRUEを返すらしいので、isSelected()がTRUEの間はパネルを更新しないようにしました。

すると、今度はパネルが全く更新されず、アイテム欄のあった場所が白く残ってしまいます。

プログラムを実行している間のisSelectedを観察してみました。始めはfalseだったのでパネルが更新されていました。メニューを選択すると、TRUEになり、パネルの更新が止まりました。メニュー選択を終えると、falseに…なると思ったのに、TRUEのままでした。なので、パネルの更新も止まったままになりました。

いろいろ調べてみたものの、解決策が思いつきません。
お知恵をお借りできないでしょうか?

3

回答

2708

閲覧

3件の回答

評価

0

isSelectedでできないなら、自前でフラグを作っては。

評価

0

もしかするとrunメソッドの中で直接Swingコンポーネントのメソッドにアクセスしているのではないでしょうか?
Swingコンポーネントのメソッドは基本的にスレッドセーフではありません。
その為Swingコンポーネントへのアクセスはイベントディスパッチスレッドという単一のスレッドでのみ行われています。
イベントリスナなどに実装しているコールバック用のメソッドはすべてイベントディスパッチスレッド上で呼び出されているので普段はあまり意識しなくても問題ないのですが、独自にスレッドを作成してそこからSwingコンポーネントにアクセスする場合にはjava.awt.EventQueue#invokeLaterメソッドを使ってイベントディスパッチスレッドで処理を行う必要があります。
repaintやrevalidate、他いくつかのスレッドセーフなSwingコンポーネントのメソッドはその内部でEventQueue#invokeLaterを呼び出して必ずイベントディスパッチスレッドで実行されるように実装されています。

よしさんの場合は定期的にパネルを更新するということですので、javax.swing.Timerを使ってみてはいかがでしょうか。
javax.swing.Timerを使う場合にはタイマーに登録したActionListenerのactionPerformedメソッドはイベントディスパッチスレッド上で呼び出されるのでSwingコンポーネントへのアクセスも安全です。

よしさんの直面している問題の原因ではないかもしれませんが、いちおうSwingの作法ということで・・・

評価

0

Timerを使うことで解決できました。

ご意見いただき、ありがとうございました。m(_ _)mペコリ

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。