C言語の関数ポインタを java で実装するパターン備忘録。
親ウィンドウからダイアログを呼び出し、ダイアログから親ウィンドウへ値を返す、よくあるシチュエーション。
FrameMain.jar 15,218kB(ソース含む)
下記 どのSTEPでも同じ動作。...▼
親ウィンドウからダイアログを呼び出し、ダイアログから親ウィンドウへ値を返す、よくあるシチュエーション。

下記 どのSTEPでも同じ動作。...▼
●STEP1 最初は 1クラスファイルだけの無名クラスで構成した実装例。
FrameMain.java
呼び先 DialogSample が呼び元 FrameMain の label を直接操作。呼び先が呼び元の操作対象を知っていなければならないので、呼び先を汎用的に再利用しにくい。
FrameMain.java
呼び先 DialogSample のインターフェース CallBack の関数 onChange() を、 呼び元 FrameMain に実装(implements)させ これを呼び出すことで情報を返す。
FrameMain.java
FrameMain.java
import java.awt.*; class FrameMain extends Frame{ Label label= new Label( "Label of FrameMain", Label.CENTER ); class DialogSample extends Dialog{ class ScrollbarSample extends Scrollbar{ ScrollbarSample(){ super( Scrollbar.HORIZONTAL ); addAdjustmentListener( new java.awt.event.AdjustmentListener(){ @Override public void adjustmentValueChanged( java.awt.event.AdjustmentEvent e ){ label.setText( String.valueOf( ScrollbarSample.this.getValue() ) ); } } ); } } DialogSample( Frame fOwner ){ super( fOwner, true );//modal addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing( java.awt.event.WindowEvent e ){ setVisible( false ); } } ); add( "Center", new ScrollbarSample() ); setSize( 200, 60 ); setVisible( true ); } } class ButtonMain extends Button{ ButtonMain( String s ){ super( s ); addActionListener( new java.awt.event.ActionListener(){ @Override public void actionPerformed( java.awt.event.ActionEvent e ){ new DialogSample( FrameMain.this ); } } ); } } FrameMain(){ addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing( java.awt.event.WindowEvent e ){ System.exit( 0 ); } } ); add( label ); add( "South", new ButtonMain( "Dialog Sample Button" ) ); setSize( 400 , 300 ); setVisible( true ); } public static void main( String[] args ){ new FrameMain(); } }●STEP2 ダイアログクラスファイルを分離した実装例。
呼び先 DialogSample が呼び元 FrameMain の label を直接操作。呼び先が呼び元の操作対象を知っていなければならないので、呼び先を汎用的に再利用しにくい。
FrameMain.java
import java.awt.*; class FrameMain extends Frame{ public Label label= new Label( "Label of FrameMain", Label.CENTER ); class ButtonMain extends Button{ ButtonMain( String s ){ super( s ); addActionListener( new java.awt.event.ActionListener(){ @Override public void actionPerformed( java.awt.event.ActionEvent e ){ new DialogSample( FrameMain.this ); } } ); } } FrameMain(){ addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing( java.awt.event.WindowEvent e ){ System.exit( 0 ); } } ); add( label ); add( "South", new ButtonMain( "Dialog Sample Button" ) ); setSize( 400 , 300 ); setVisible( true ); } public static void main( String[] args ){ new FrameMain(); } }DialogSample.java
import java.awt.*; class DialogSample extends Dialog{ Frame fOwner; class ScrollbarSample extends Scrollbar{ ScrollbarSample(){ super( Scrollbar.HORIZONTAL ); addAdjustmentListener( new java.awt.event.AdjustmentListener(){ @Override public void adjustmentValueChanged( java.awt.event.AdjustmentEvent e ){ //▼▼▼ ((FrameMain)DialogSample.this.fOwner).label.setText( String.valueOf( ScrollbarSample.this.getValue() ) ); //▲▲▲ } } ); } } DialogSample( Frame fOwner ){ super( fOwner, true );//modal //▼▼▼ this.fOwner= fOwner; //▲▲▲ addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing( java.awt.event.WindowEvent e ){ setVisible( false ); } } ); //▼▼▼ add( "Center", new ScrollbarSample() ); //▲▲▲ setSize( 200, 60 ); setVisible( true ); } }●STEP3 java の インターフェース(interface) を使った コールバック(callback)実装例。
呼び先 DialogSample のインターフェース CallBack の関数 onChange() を、 呼び元 FrameMain に実装(implements)させ これを呼び出すことで情報を返す。
FrameMain.java
import java.awt.*; //▼▼▼ class FrameMain extends Frame implements DialogSample.CallBack{ public void onChange( DialogSample dialogSample ){ label.setText( String.valueOf( dialogSample.scrollbarSample.getValue() ) ); } //▲▲▲ public Label label= new Label( "Label of FrameMain", Label.CENTER ); class ButtonMain extends Button{ ButtonMain( String s ){ super( s ); addActionListener( new java.awt.event.ActionListener(){ public void actionPerformed( java.awt.event.ActionEvent e ){ new DialogSample( FrameMain.this ); } } ); } } FrameMain(){ addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing( java.awt.event.WindowEvent e ){ System.exit( 0 ); } } ); add( label ); add( "South", new ButtonMain( "Dialog Sample Button" ) ); setSize( 400 , 300 ); setVisible( true ); } public static void main( String[] args ){ new FrameMain(); } }DialogSample.java
import java.awt.*; class DialogSample extends Dialog{ //▼▼▼ public interface CallBack{ abstract void onChange( DialogSample d ); } CallBack callBack= null; //▲▲▲ //▼▼▼ ScrollbarSample scrollbarSample= new ScrollbarSample();//呼び元から参照させる //▲▲▲ class ScrollbarSample extends Scrollbar{ ScrollbarSample(){ super( Scrollbar.HORIZONTAL ); addAdjustmentListener( new java.awt.event.AdjustmentListener(){ public void adjustmentValueChanged( java.awt.event.AdjustmentEvent e ){ //▼▼▼ callBack.onChange( DialogSample.this ); //▲▲▲ } } ); } } DialogSample( Frame fOwner ){ super( fOwner, true );//modal //▼▼▼ callBack= (CallBack)fOwner;//CallBack implemented Frame //▲▲▲ addWindowListener( new java.awt.event.WindowAdapter(){ public void windowClosing( java.awt.event.WindowEvent e ){ setVisible( false ); } } ); //▼▼▼ add( "Center", scrollbarSample ); //▲▲▲ setSize( 200, 60 ); setVisible( true ); } }呼び先 DialogSample は、呼び元 FrameMain の label を参照せず(知らなくとも)情報を返すことを実現。DialogSample のインターフェースを実装さえすれば DialogSample を再利用可能に。lambda expression(ラムダ式)、annotation()アノテーション、swing(スウィング) すら使っていない基本形。