// surce 抜粋 from ./frac/e_mand.jar public class Canvas_mand5 extends java.awt.Applet { // applet init :: canvas & panel layout public void init() { // 略 } // main=standalone frame(550,400) public static void main(String args[]) { java.awt.Frame f = new fracFrame("Mandelbrot-Test"); Canvas_mand5 Canvas_mand5 = new Canvas_mand5(); Canvas_mand5.init(); f.add("Center", Canvas_mand5); // 略 } // window close adapter class WindowClose extends java.awt.event.WindowAdapter { public void windowClosing(java.awt.event.WindowEvent e) { System.exit(0); } } // frame window lisner event setting class fracFrame extends java.awt.Frame { public fracFrame( String title) { setTitle(title); WindowClose w = new WindowClose(); addWindowListener(w); } }でもなんか冗長だなーと思っていたところ、
javax.swing.JFrame jframe = new javax.swing.JFrame(); jframe.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
Class-Path: ./ Main-Class: FracDOS窓(または、OSのコマンドライン)でクラスファイルとソースファイルのあるディレクトリーに移動し以下を実行。
c:\>cd c:\java\src c:\java\src>jar fcvm name.jar manifest.mf *.class *.java※ 注:pathにjavaの実行ディレクトリーが設定済みであること
c:\java\src>java_install\bin\jar fcvm name.jar mani_frac.mf miz/* *.class *.java c:\java\src>"c:\Program Files\java\jdk1.4\bin\jar" fcvm name.jar mani_frac.mf *.class *.java
c:\>jar -help
//surce 抜粋 from frac_sw4.jar内のFracPack.java一部簡素化 public class FracPack extends AAJframe { // ↑public class AAJframe extends javax.swing.JApplet public void init() { // コンテント・ペインの取得 java.awt.Container cont = this.getContentPane(); // コンテント・ペインの背景色変更 cont.setBackground(java.awt.Color.white); SimpleCanvas canvas = new SimpleCanvas(900,900); // ↑public class SimpleCanvas extends JComponent // コンテント・ペインにコンポーネントを載せる cont.add( canvas ); // 見えるようにする; show()よりはsetVisible推奨とのこと cont.setVisible(true); } }
//surce 抜粋 from ./swing1_4/jpuzzle8.jar //あるクラスのボタンアクション内 java.awt.Frame parentFrame; java.awt.Component co = this.getParent(); while( ( co != null) && (!( co instanceof java.awt.Frame)) ){ co = co.getParent(); // System.out.println(co.toString() ); // debug } if(co != null){ parentFrame = (java.awt.Frame) co; // 以下ダイアログの呼び出し 省略 }その後さらにいろいろなサイトを見ていたら、こういうmethodに出来ることが解りました。 サイトリンクを付けようと思ったけど、どこの掲示板だったか忘れましたm(_ _)m。
// surce 抜粋 from ./swing1_4/frac_sw4.jar 内 miz/miz_util/ResultPanel.java protected java.awt.Frame getFrame() { for (java.awt.Container p = getParent(); p != null; p = p.getParent()) { if (p instanceof java.awt.Frame) { return (java.awt.Frame) p; } } return null; }whileではなくforで回してるところが奥が深い(◎_◎)。
// 例 JDialog を閉じるボタン class XXDialog extends javax.swing.JDialog{ XXDialog(String msg){ // constructor java.awt.Container con = getContentPane(); con.add( new javax.swing.JLabel(msg) ); javax.swing.JButton cl_button = new javax.swing.JButton("close"); cl_button.addActionListener( new java.awt.event.ActionListener(){ public void actionPerformed(java.awt.event.ActionEvent ev) { javax.swing.SwingUtilities.getWindowAncestor((java.awt.Component)ev.getSource()) .setVisible(false); } }); con.add(cl_button); } }SwingUtilities.getWindowAncestorの返値は、java.awt.Window型なので、 そのままでは、Frame型の引数には渡せないので、 以下のようにinstanceofチェックを掛けたり、castする必要があります。
java.awt.Frame getFrame(java.awt.Component c) { java.awt.Window w = javax.swing.SwingUtilities.getWindowAncestor(c); if( w != null && w instanceof java.awt.Frame ){ return (java.awt.Frame)w; } return null; }
//surce 抜粋 from ./swing1_4/jpuzzle8.jar class PuzzleRemaker extends JPanel implements java.awt.event.ActionListener { public void actionPerformed(ActionEvent ev) { java.awt.Frame parentFrame = getFrame(); // modaldialog表示のための基準frame取得 if(parentFrame != null){ EndPointPanel end_dialog = new EndPointPanel(parentFrame ,true, this); end_dialog.pack(); end_dialog.show(); } } } class EndPointPanel extends javax.swing.JDialog implements java.awt.event.ActionListener{ private PuzzleRemaker p_make; public EndPointPanel(java.awt.Frame owner, boolean modal, PuzzleRemaker jpm){ super( owner, modal); // make and set JDialog this.p_make = jpm; } public void actionPerformed(ActionEvent ev) { p_make.set_present(); p_make.puzzle.repaint(); hide(); } }
class FractalResult extends javax.swing.JPanel implements java.awt.event.ActionListener { public void actionPerformed(ActionEvent ev) { java.awt.Frame parentFrame = getFrame(); // modaldialog表示のための基準frame取得 if(parentFrame != null){ OkCancelDialog msg_dialog = new OkCancelDialog(parentFrame, "同名ファイルが存在します "+imagefile+" 上書きしてよいですか" ) ; msg_dialog.show(); boolean save_ok = msg_dialog.getResult(); } } } class OkCancelDialog extends javax.swing.JDialog implements java.awt.event.ActionListener { private boolean return_var = false; // default: windowの×で閉じてもcancelにセット public OkCancelDialog(java.awt.Frame owner, String msg ){ super( owner, true); // make and set JDialog, mode true= modal dialog set_Panel(msg); } public void actionPerformed(ActionEvent ev) { if(ev.getSource() == ok_button){ return_var = true; }else{ return_var = false; } hide(); } public boolean getResult(){ return return_var; } }
// surce 抜粋 from ./swing1_4/frac_sw4.jar 内 miz/miz_util/ResultPanel.java private javax.swing.JTextArea result_memo; // 情報表示jtextarea private javax.swing.JPopupMenu copy_menu; // 右クリックメニュー private String[] menu_str = {"copy","cut","paste"}; private javax.swing.JComponent setupMemo(int xwidth, int yheight){ result_memo = new javax.swing.JTextArea(); // 行数と列数は指定しなくても自動的に領域拡張する result_memo.setLineWrap(true); // 自動改行にする。 // マウス右クリックメニュー作成 copy_menu = new javax.swing.JPopupMenu(); for(int i=0; i<menu_str.length; i++ ){ javax.swing.JMenuItem item = new javax.swing.JMenuItem(menu_str[i]); item.addActionListener(this); // this = 載せてるクラス copy_menu.add(item); } copy_menu.setVisible(false); // 見えなくしておく // マウスクリックイベントMouseAdapter()の作成&登録 result_memo.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(MouseEvent ev) { // v1.4 では int getButton() で 数値比較可能 if ( ev.getButton() == 3) { // mouse button3 = 右クリック copy_menu.show( (Component)(ev.getSource()), ev.getX(), ev.getY() ); } } } ); javax.swing.JScrollPane jscrlp= new javax.swing.JScrollPane(result_memo); // JTextArea は必ずJScrollPaneに載せる jscrlp.setPreferredSize(new java.awt.Dimension(xwidth,yheight)); // JScrollPaneのサイズ指定 return jscrlp; } // 載せたいクラスのコンストラクタ内で add( setupMemo(200, 100) ); /* // 載せてるクラスにimplements ActionListenerしておく * item.addActionListener(this); によりクラス内に実装されたactionPerformedが呼び出される */ public void actionPerformed(ActionEvent ev) { if( ev.getSource() instanceof javax.swing.JMenuItem){ String str = ( (javax.swing.JMenuItem)ev.getSource() ).getText(); if( str.equals(menu_str[0]) ){ // copy result_memo.copy(); }else if( str.equals(menu_str[1]) ){ // cut result_memo.cut(); }else if( str.equals(menu_str[2]) ){ // paste result_memo.paste(); } } }
item.addActionListener(this);するには、item = new javax.swing.JMenuItem(menu_str[i]);とcopy_menu.add(item);で一個ずつ載せていくしかないのですね。
copy_menu = new javax.swing.JPopupMenu(String[] menu_str);引数に配列を入れて簡単にメニュー表示にはなるけど、これだと各ボタンクリックエベントが実装出来ないのです。
// class propaty private String[] bi_str={"初期値に戻す","実行"}; // constructor method 内 public classname(){ JButton bi = new JButton(bi_str[0]); bi.addActionListener(this); bi.setActionCommand(bi_str[0]); add(bi); bi = new JButton(bi_str[1]); bi.addActionListener(this); bi.setActionCommand(bi_str[1]); add(bi); } // ボタンのアクション: public void actionPerformed(ActionEvent ev) { String action = ev.getActionCommand(); if (action.equals(bi_str[0])){ // 省略 }else if(action.equals(bi_str[1])){ // 省略 } }
// surce 抜粋 一部改変 from ./simulate/ray3.jar 内 miz/ray/RayMenu.java(JMenuBar class) public class RayMenu extends javax.swing.JMenuBar implements java.awt.ActionListener{ // class propaty private String[] set_str = { "準備済みデータ集", "準備済みマップ画像取り込み" }; private String[] load_str = { "Load(データ読み込みダイアログ)", "マップ画像取り込みダイアログ" }; private String ctrl_str = "計算開始"; // class constructor()、引数一部省略 public RayMenu(boolean applet_flag) { // 一部省略 javax.swing.JMenu menu1 ; javax.swing.JMenuItem item; // レイ・トレーシング計算開始button menu1 = new javax.swing.JMenu(ctrl_str +" alt-G"); menu1.setMnemonic(java.awt.event.KeyEvent.VK_G ); // short cut key 登録 add(menu1); // javax.swing.event.MenuListenerの無名クラス作成と登録 menu1.addMenuListener( new javax.swing.event.MenuListener(){ public void menuSelected(javax.swing.event.MenuEvent e){ make_image(); } public void menuCanceled(javax.swing.event.MenuEvent e){ } public void menuDeselected(javax.swing.event.MenuEvent e) { } } ); if (!applet_flag) { // application実行の時のみ外へのデータアクセスmenuを付ける menu1 = new javax.swing.JMenu("データの読込 alt-L"); menu1.setMnemonic(java.awt.KeyEvent.VK_L ); add(menu1); for (int i = 0; i < load_str.length; i++) { item = new javax.swing.JMenuItem(load_str[i]); item.addActionListener(this); item.setActionCommand(load_str[i]); item.setAccelerator( javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent.VK_L+i, java.awt.event.ActionEvent.ALT_MASK)); // ALTのキー名が他のメニューと重なっても選択表示中のもののみ有効 menu1.add(item); } } } public void actionPerformed(ActionEvent e) { String action = e.getActionCommand(); for( int i=0; i < data_ary.length; i++){ if (action.equals(data_ary[i])){ // 省略 } } }
// surce 抜粋 from ./swing1_4/frac_sw4.jar 内 miz/miz_util/ResultPanel.java // FileDialog.SAVEで保存ファイル名File imagefile取得後に int value = javax.swing.JOptionPane.YES_OPTION; // 存在しなければyesで保存 if(imagefile.exists() ){ value = javax.swing.JOptionPane.showConfirmDialog( this , "同名ファイルが存在します、"+imagefile+" を上書きしてよいですか" , "同名ファイルチェック" , javax.swing.JOptionPane.YES_NO_OPTION ); } if (value == javax.swing.JOptionPane.YES_OPTION){ javax.imageio.ImageIO.write(saveimage, image_type, imagefile); javax.swing.JOptionPane.showMessageDialog( this , "ファイル名 "+imagefile+" で保存しました" , "保存完了" , javax.swing.JOptionPane.INFORMATION_MESSAGE ); }
// 例 JComboBox の選択によって、object入れ替え private javax.swing.JComboBox obj_menus,op_menus; private javax.swing.JPanel obj_panel; public void itemStateChanged(ItemEvent ev) { obj_panel.removeAll( ); InputData inner_panel; // 入力画面作成用 int s_num=0; if( ev.getItemSelectable() == obj_menus) { // 選択を行ったboxの同定 s_num = obj_menus.getSelectedIndex(); } inner_panel = new InputData( this, s_num); // s_num によって異なる画面作成 obj_panel.add(inner_panel); /* obj_panel.invalidate(); getParent().getParent().validate(); // 親を再配置すると、子コンポーネントも再描画される */ ((JComponent)getParent()).revalidate(); // 親がJComponent派生クラス ならrevalidate();一行でokだが、クラスcast必須 }※ すべてjavax.swing.JComponentのサブクラスで出来てるなら、親のrevalidate();のみでよい。
// 上記コードを、getRoot() で書き直してみる java.awt.Component parent = javax.swing.SwingUtilities.getRoot(obj_panel); obj_panel.invalidate(); parent.validate();
java.awt.Frame parentFrame = getFrame(); // modaldialog,filedialog 表示のための基準frame取得 if(parentFrame != null){ java.awt.FileDialog save_dialog = new java.awt.FileDialog( parentFrame, "画像保存ファイル名を指定", java.awt.FileDialog.SAVE); save_dialog.show(); if( save_dialog.getFile() != null ){ java.io.File imagefile = new java.io.File( save_dialog.getDirectory(), save_dialog.getFile() ); // JOptionPaneのところで載せたコ−ドが入る } }アプリケーション起動の時は、これで指定先に保存出来ますが、 Appletの時は、SandBoxという制限に引っ掛かって、 インターネット上のAppletからローカルにデータを保存することは出来ません。
// surce 抜粋 from ./simulate/ray3.jar 内 miz/ray/data/RaySpace.java /** fileからデータを取り込む * @param infile : 取り込み元ファイル名 * @return int : error flag; 0 =no error, 2 = no file, 10 = else; */ int load_from_infile(String infile ){ String str = null; int flag=0; java.net.URL this_url = null; java.io.BufferedReader reader; try { // jar 内または外部ディレクトリから読み込む。 ブラウザappletでも同じ this_url = this.getClass().getClassLoader().getResource(infile); if( this_url != null ){ java.io.InputStream is = this_url.openStream(); try{ if ( (reader = new java.io.BufferedReader( new java.io.InputStreamReader(is) )) != null) { flag = get_lines( reader ); // 自作read関数 str = "url-readed:"; } } catch (Exception ex) { System.out.println("error : " + ex.toString() ); // debug str = "stream read error;"+str; flag = 2; } finally { is.close(); } }else{ /* // jar実行ではなく直接JVM実行の時 フルパス指定(FileDialog で取得)で読み込む * 一応こちらの記述も入れているけど、ファイル名の記述間違いがなければ、直接JVM実行の時も * this.getClass().getClassLoader().getResource()でURL取得出来ている。 */ java.io.FileReader fr = new java.io.FileReader(infile); try{ if ((reader = new java.io.BufferedReader( fr )) != null) { flag = get_lines( reader ); // 自作read関数 str = "file:" ; } } catch (Exception ex) { System.out.println("error : " + ex.toString() ); // debug str = "file read error;"+str; flag = 2; } finally { fr.close(); } } } catch (Exception e) { str="open error"; flag = 10; } return flag; } // surce 抜粋 from ./simulate/ray3.jar 内 miz/ray/data/ShowMap.java /** 画像fileからテクスチャーマップ画像を取り込む * @param map_file : 取り込み元ファイル名 * @param ray_data : テクスチャー情報登録用インスタンス * @return String : 作業状況メッセージ; */ public String map_load( String map_file, DataFactory ray_data){ StringBuffer msg= new StringBuffer("texture load "); msg.append( map_file + " : " ); java.net.URL url = null; try{ url = this.getClass().getClassLoader().getResource(map_file); java.awt.Image image= null; java.awt.MediaTracker mt; if( url != null ){ image = java.awt.Toolkit.getDefaultToolkit().getImage( url ); }else{ System.out.println("image url error ?;"); // debug image = java.awt.Toolkit.getDefaultToolkit().getImage(map_file); System.out.println("image name:"+map_file); // debug } if( image != null ){ // 指定されたコンポーネント(this)のイメージを監視する mt = new java.awt.MediaTracker(this); mt.addImage(image, 0); mt.waitForAll(); // PixelGrabberで色データをint[]に得る int w = image.getWidth(this); int h = image.getHeight(this); int[] data= new int[w*h]; java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber( image, 0,0, w,h,data, 0,w); pg.grabPixels(); // テクスチャー情報登録 int ti = ray_data.add_texture(w,h, data, map_file); this.addMap(ti,image); // 自作method msg.append( " load完了\n" ); }else{ msg.append( " file error\n" ); } }catch ( Exception ex) { System.out.println("image load error ;" + ex.toString()); // debug javax.swing.JOptionPane.showMessageDialog(this, "マッピング用画像の取り込みに失敗しました", "読込エラー", javax.swing.JOptionPane.WARNING_MESSAGE); msg.append( "画像の取り込み失敗\n" ); } return msg.toString(); }
// surce 抜粋 from ./simulate/ray3.jar 内 miz/util/SimpleCanvas.java public class SimpleCanvas extends javax.swing.JComponent { protected java.awt.image.BufferedImage offset_img; /** constructor : setPreferredSize 指定 * @param width : canvas width * @param height : canvas height */ public SimpleCanvas(int width, int height){ setPreferredSize(new java.awt.Dimension(width, height) ); // これで、JScrollpaneに対し強制sizeになる setImage( width, height ); } /** 初期画像の作成 */ private void setImage(int width, int height ){ // 白画面作成:コンストラクターからも実行可能 offset_img = new java.awt.image.BufferedImage( width, height, java.awt.image.BufferedImage.TYPE_INT_RGB); java.awt.Graphics dt_g = offset_img.getGraphics(); dt_g.setColor(java.awt.Color.white); // 背景色 dt_g.fillRect( 0,0, width, height); // 右上x0,y0, 左下x2,y2 dt_g.dispose(); } public void paintComponent(Graphics g){ super.paintComponent(g); // 必ず先頭で実行すること int mwidth = offset_img.getWidth(this); int mheight= offset_img.getHeight(this); int mxw= this.getWidth(), myh= this.getHeight(); g.setColor(java.awt.Color.black); // 背景色 g.fillRect( 0,0, mxw, myh); g.drawImage(offset_img, 0,0,mwidth,mheight, 0,0, mwidth,mheight, this); } // 他method省略 }※ 背景の塗り潰しについて:JComponentは透明なのと、プラットホームによって背景色が微妙に違うのを統一するためにこの作業をしていますが、 JPanelを使った時にもよけいなものが写り込んでたのは、super.paintComponent(g)の実行位置を間違えていたせいのよう。