Swing部品の標準Look & Feelのときの処理 (ボタン部品のアクションイベントについて) は以下のようになっている。
JDK のソースをいくら見てもわからず、結局、JBuilder Personal 9 日本語版 と添付のJDK 1.4.1_02-b06 でイベント処理用メソッドにデバッガのブレークをかけて調べた結果である。
非常にややこしいが、何というか勉強になった気がする。
[処理の概要説明]
ボタン構築時に
javax.swing.plaf.basic.BasicButtonUI
クラスで、
javax.swing.plaf.basic.BasicButtonListener
クラスのインスタンスが、ボタンの MouseListener, addMouseMotionListener, FocusListener, ChangeListener, PropertyChangeListener として登録されている。
ボタンクリックのマウスイベントは、 java.awt.Component の protected void processEvent(AWTEvent e) から protected void processMouseEvent(MouseEvent e) で処理されるが、その中でリスナとして
javax.swing.plaf.basic.BasicButtonListener
クラスのインスタンスの該当メソッドが呼び出されることになる。
ボタンクリック時には、このリスナの
mouseReleased()
から、ボタンの getModel() によって得られる ButtonModel の setPressed(true) が呼び出される。
JButton の場合は、
javax.swing.DefaultButtonModel の setPressed()
が呼ばれ、そこで
javax.swing.DefaultButtonModel の protected void fireActionPerformed(ActionEvent e)
が呼ばれる。
(JCheckBox など JToggleButton の場合は、
javax.swing.JToggleButton.ToggleButtonModel (内部staticクラス。DefaultButtonModelのサブクラス) の setPressed()
が呼ばれ、そこでトグルチェックをやった後
javax.swing.DefaultButtonModel の protected void fireActionPerformed(ActionEvent e)
が呼ばれる。)
DefaultButtonModel の fireActionPerformed() では、 インスタンス変数である
protected EventListenerList listenerList (java.util.EventListener クラス)
を参照し、登録されている ActionListener を順次検索し、それぞれの
public void ationPerformed(ActionEvent e)
を順次呼び出している。
※ なお、JButton や JCheckBox などのボタンでは DefaultButtonModel の listenerList がイベント発火のときに使用され、JComponent に用意されているインスタンス変数
protected EventListenerList listenerList
は使用していないようだ。
AbstractButton の addActionListener 等のコードでは JComponent の listenerList を利用しているのだが...
不思議だ。
[ボタンクリックからイベント処理用メソッドに至るまでのスタックトレース]
以下は (A) JButtonnクリック時 (B) JCheckBoxクリック時 のイベント処理用メソッドに至るまでのスタックトレースである。
(A) JButtonをクリックしたとき
処理用メソッド
jButton1_actionPerformed() : 104, フレームクラス, ソース.java
登録してあるリスナのイベントハンドラ
actionPerformed() : 177, アダプタクラス, ソース.java
fireActionPerformed() : 1764, javax.swing.AbstractButton, AbstractButton.java
actionPerformed() : 1817, javax.swing.AbstractButton$ForwardActionEvents, AbstractButton.java
fireActionPerformed() : 419, javax.swing.DefaultButtonModel, DefaultButtonModel.java
setPressed() : 257, javax.swing.DefaultButtonModel, DefaultButtonModel.java
mouseReleased() : 245, javax.swing.plaf.basic.BasicButtonListener, BasicButtonListener.java
processMouseEvent() : 5134, java.awt.Component, Component.java
processEvent() : 4931, java.awt.Component, Component.java
processEvent() : 1566, java.awt.Container, Container.java
dispatchEventImpl() : 3639, java.awt.Component, Component.java
dispatchEventImpl() : 1623, java.awt.Container, Container.java
dispatchEvent() : 3480, java.awt.Component, Component.java
retargetMouseEvent() : 3450, java.awt.LightweightDispatcher, Container.java
processMouseEvent() : 3165, java.awt.LightweightDispatcher, Container.java
dispatchEvent() : 3095, java.awt.LightweightDispatcher, Container.java
dispatchEventImpl() : 1609, java.awt.Container, Container.java
dispatchEventImpl() : 1590, java.awt.Window, Window.java
dispatchEvent() : 3480, java.awt.Component, Component.java
dispatchEvent() : 450, java.awt.EventQueue, EventQueue.java
pumpOneEventForHierarchy() : 197, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEventsForHierarchy() : 150, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 144, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 136, java.awt.EventDispatchThread, EventDispatchThread.java
run() : 99, java.awt.EventDispatchThread, EventDispatchThread.java
(B) JCheckBox (JToggleButtonの一種) をクリックしたとき
処理用メソッド
jCheckBox1_actionPerformed() : 156, フレームクラス, ソース.java
登録してあるリスナのイベントハンドラ
actionPerformed() : 216, アダプタクラス, ソース.java
fireActionPerformed() : 1764, javax.swing.AbstractButton, AbstractButton.java
actionPerformed() : 1817, javax.swing.AbstractButton$ForwardActionEvents, AbstractButton.java
fireActionPerformed() : 419, javax.swing.DefaultButtonModel, DefaultButtonModel.java
setPressed() : 273, javax.swing.JToggleButton$ToggleButtonModel, JToggleButton.java
mouseReleased() : 245, javax.swing.plaf.basic.BasicButtonListener, BasicButtonListener.java
processMouseEvent() : 5134, java.awt.Component, Component.java
processEvent() : 4931, java.awt.Component, Component.java
processEvent() : 1566, java.awt.Container, Container.java
dispatchEventImpl() : 3639, java.awt.Component, Component.java
dispatchEventImpl() : 1623, java.awt.Container, Container.java
dispatchEvent() : 3480, java.awt.Component, Component.java
retargetMouseEvent() : 3450, java.awt.LightweightDispatcher, Container.java
processMouseEvent() : 3165, java.awt.LightweightDispatcher, Container.java
dispatchEvent() : 3095, java.awt.LightweightDispatcher, Container.java
dispatchEventImpl() : 1609, java.awt.Container, Container.java
dispatchEventImpl() : 1590, java.awt.Window, Window.java
dispatchEvent() : 3480, java.awt.Component, Component.java
dispatchEvent() : 450, java.awt.EventQueue, EventQueue.java
pumpOneEventForHierarchy() : 197, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEventsForHierarchy() : 150, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 144, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 136, java.awt.EventDispatchThread, EventDispatchThread.java
run() : 99, java.awt.EventDispatchThread, EventDispatchThread.java
JDK のソースをいくら見てもわからず、結局、JBuilder Personal 9 日本語版 と添付のJDK 1.4.1_02-b06 でイベント処理用メソッドにデバッガのブレークをかけて調べた結果である。
非常にややこしいが、何というか勉強になった気がする。
[処理の概要説明]
ボタン構築時に
javax.swing.plaf.basic.BasicButtonUI
クラスで、
javax.swing.plaf.basic.BasicButtonListener
クラスのインスタンスが、ボタンの MouseListener, addMouseMotionListener, FocusListener, ChangeListener, PropertyChangeListener として登録されている。
ボタンクリックのマウスイベントは、 java.awt.Component の protected void processEvent(AWTEvent e) から protected void processMouseEvent(MouseEvent e) で処理されるが、その中でリスナとして
javax.swing.plaf.basic.BasicButtonListener
クラスのインスタンスの該当メソッドが呼び出されることになる。
ボタンクリック時には、このリスナの
mouseReleased()
から、ボタンの getModel() によって得られる ButtonModel の setPressed(true) が呼び出される。
JButton の場合は、
javax.swing.DefaultButtonModel の setPressed()
が呼ばれ、そこで
javax.swing.DefaultButtonModel の protected void fireActionPerformed(ActionEvent e)
が呼ばれる。
(JCheckBox など JToggleButton の場合は、
javax.swing.JToggleButton.ToggleButtonModel (内部staticクラス。DefaultButtonModelのサブクラス) の setPressed()
が呼ばれ、そこでトグルチェックをやった後
javax.swing.DefaultButtonModel の protected void fireActionPerformed(ActionEvent e)
が呼ばれる。)
DefaultButtonModel の fireActionPerformed() では、 インスタンス変数である
protected EventListenerList listenerList (java.util.EventListener クラス)
を参照し、登録されている ActionListener を順次検索し、それぞれの
public void ationPerformed(ActionEvent e)
を順次呼び出している。
※ なお、JButton や JCheckBox などのボタンでは DefaultButtonModel の listenerList がイベント発火のときに使用され、JComponent に用意されているインスタンス変数
protected EventListenerList listenerList
は使用していないようだ。
AbstractButton の addActionListener 等のコードでは JComponent の listenerList を利用しているのだが...
不思議だ。
[ボタンクリックからイベント処理用メソッドに至るまでのスタックトレース]
以下は (A) JButtonnクリック時 (B) JCheckBoxクリック時 のイベント処理用メソッドに至るまでのスタックトレースである。
(A) JButtonをクリックしたとき
処理用メソッド
jButton1_actionPerformed() : 104, フレームクラス, ソース.java
登録してあるリスナのイベントハンドラ
actionPerformed() : 177, アダプタクラス, ソース.java
fireActionPerformed() : 1764, javax.swing.AbstractButton, AbstractButton.java
actionPerformed() : 1817, javax.swing.AbstractButton$ForwardActionEvents, AbstractButton.java
fireActionPerformed() : 419, javax.swing.DefaultButtonModel, DefaultButtonModel.java
setPressed() : 257, javax.swing.DefaultButtonModel, DefaultButtonModel.java
mouseReleased() : 245, javax.swing.plaf.basic.BasicButtonListener, BasicButtonListener.java
processMouseEvent() : 5134, java.awt.Component, Component.java
processEvent() : 4931, java.awt.Component, Component.java
processEvent() : 1566, java.awt.Container, Container.java
dispatchEventImpl() : 3639, java.awt.Component, Component.java
dispatchEventImpl() : 1623, java.awt.Container, Container.java
dispatchEvent() : 3480, java.awt.Component, Component.java
retargetMouseEvent() : 3450, java.awt.LightweightDispatcher, Container.java
processMouseEvent() : 3165, java.awt.LightweightDispatcher, Container.java
dispatchEvent() : 3095, java.awt.LightweightDispatcher, Container.java
dispatchEventImpl() : 1609, java.awt.Container, Container.java
dispatchEventImpl() : 1590, java.awt.Window, Window.java
dispatchEvent() : 3480, java.awt.Component, Component.java
dispatchEvent() : 450, java.awt.EventQueue, EventQueue.java
pumpOneEventForHierarchy() : 197, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEventsForHierarchy() : 150, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 144, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 136, java.awt.EventDispatchThread, EventDispatchThread.java
run() : 99, java.awt.EventDispatchThread, EventDispatchThread.java
(B) JCheckBox (JToggleButtonの一種) をクリックしたとき
処理用メソッド
jCheckBox1_actionPerformed() : 156, フレームクラス, ソース.java
登録してあるリスナのイベントハンドラ
actionPerformed() : 216, アダプタクラス, ソース.java
fireActionPerformed() : 1764, javax.swing.AbstractButton, AbstractButton.java
actionPerformed() : 1817, javax.swing.AbstractButton$ForwardActionEvents, AbstractButton.java
fireActionPerformed() : 419, javax.swing.DefaultButtonModel, DefaultButtonModel.java
setPressed() : 273, javax.swing.JToggleButton$ToggleButtonModel, JToggleButton.java
mouseReleased() : 245, javax.swing.plaf.basic.BasicButtonListener, BasicButtonListener.java
processMouseEvent() : 5134, java.awt.Component, Component.java
processEvent() : 4931, java.awt.Component, Component.java
processEvent() : 1566, java.awt.Container, Container.java
dispatchEventImpl() : 3639, java.awt.Component, Component.java
dispatchEventImpl() : 1623, java.awt.Container, Container.java
dispatchEvent() : 3480, java.awt.Component, Component.java
retargetMouseEvent() : 3450, java.awt.LightweightDispatcher, Container.java
processMouseEvent() : 3165, java.awt.LightweightDispatcher, Container.java
dispatchEvent() : 3095, java.awt.LightweightDispatcher, Container.java
dispatchEventImpl() : 1609, java.awt.Container, Container.java
dispatchEventImpl() : 1590, java.awt.Window, Window.java
dispatchEvent() : 3480, java.awt.Component, Component.java
dispatchEvent() : 450, java.awt.EventQueue, EventQueue.java
pumpOneEventForHierarchy() : 197, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEventsForHierarchy() : 150, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 144, java.awt.EventDispatchThread, EventDispatchThread.java
pumpEvents() : 136, java.awt.EventDispatchThread, EventDispatchThread.java
run() : 99, java.awt.EventDispatchThread, EventDispatchThread.java
※コメント投稿者のブログIDはブログ作成者のみに通知されます