Delphi動的なフォーム生成について

このQ&Aのポイント
  • Delphiにおける動的なフォーム生成についての疑問です。
  • フォームのインスタンスを作成する際、古いインスタンスはどうなるのか、また、フォームを再作成する際にはどのようにすれば良いのかについて教えてください。
  • 実際にフォームを再作成しようとした際、アクセス違反のエラーが発生しました。このエラーの原因と対処方法についても教えてください。
回答を見る
  • ベストアンサー

《 Delphi 》 動的なフォーム生成について

プログラムをしていて疑問に思ったのですが、たとえば Form1 := Tform1.create(Application); として、Form1(設計済み)のインスタンスを作って表示させたとします。 ここで、更に Tform1.create を行った場合、Form1の参照先は新しく作ったほうになると思うのですが、古いほうのインスタンスはどうなるのでしょうか?Form1に属するメンバはやはりゴミとして残るのでしょうか。 また、Form1を消去して新たに作り直したい場合は、Form1.Releaseをしてから再度Createすれば問題はないのでしょうか。 実は、Releaseしてから再Createしたところ、Form自体はできたのですが、Form上のImageをCreateする段階でアクセス違反が起きて落ちてしまいまして・・・(Form1にはImageがひとつ乗っており、Form生成時にImageも生成されます)。 ソースを削って原因究明したところ、関係ない変数を代入すると発生したり収まったりして、もしやメモリを蝕んでいる!?とか思ったもので・・・。 思い当たる節がありましたら、ご教授いただければ嬉しいです。

質問者が選んだベストアンサー

  • ベストアンサー
  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.2

こんにちは。 メインのForm2にButtonを1つを置き、プロジェクトのオプションでForm1の自動作成を「選択可能」へ写して、Form2のButton1のClickイベントに procedure TForm2.Button1Click(Sender: TObject); var Frm : TForm1; begin  Frm := TForm1.Create(Application);  try   Self.Hide;   Frm.ShowModal;  finally   Self.Show;   Frm.Release;  end; end; とかやってみました。 こんなイメージでしょうか?

pythian
質問者

お礼

ありがとうございます。この方法で行けると思ったのですが、アクセス違反が発生してしまいました。 TForm1.Create(Application); としてから、Form1.OnCreate内にて Timage.create(form1); をしているのですが、一度破棄して再度imageを作ろうとするとコケるようです。メモリリークも確認しましたが、していないようです・・・。

その他の回答 (3)

  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.4

こんにちは。 > どうやらフォーム上で用いたオブジェクトの解放の方法に問題があったようです。 この場合フォームに動的に作成して配置したTImageはフォームが破棄される時に自動的に破棄されると認識してますが、、、

pythian
質問者

お礼

TImageのほかに元々Formに乗っていたDirectX関係のオブジェクトが原因でした。 簡単に説明しようとして端折りすぎてしまいました。Image生成時に落ちていたので、てっきりImageのせいだと思っていたので・・・申し訳ないですm(_ _)m

  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.3

こんにちは。 不具合の再現できる最小限のソースを提示されてはどうでしょう? Form1 のUses に ExtCtrls, ClipBrd, StdCtrls を追加して、 procedure TForm1.FormCreate(Sender: TObject); begin  if Clipboard.HasFormat(CF_TEXT) then begin    with TMemo.Create(Self) do begin      Parent := Self;      Align := alClient;      Lines.Add(Clipboard.AsText);    end;  end else  if Clipboard.HasFormat(CF_PICTURE) then begin    with TImage.Create(Self) do begin      Parent := Self;      Align := alClient;      AutoSize := True;      Picture.Assign(Clipboard);    end;  end; end; ペイントなどから画像をクリップボードにコピーしてから実行すると Form1 に画像が表示され、文字だとメモが表示されます。こちらでは何回呼んでもアクセス違反は発生しないようです。

pythian
質問者

お礼

最小限まで削ってみたのですが、削っていくとEAccessViolationがEAbstractErrorになったり、全く無関係の場所を削っただけでエラーが出なくなったりと、手に負えなくなってしまいました。それで今日、TImageの親をForm1からForm2あるいはSelfにしたところ、生成時のエラーが出なくなり、フォームの再生成ができるようになりました。ただし、今度は2回目にReleaseしようとするとアクセス違反になってしまいましたが・・・。 何度も申し訳ありません。もう少し調べてみます。

pythian
質問者

補足

すみません、「発生原因が不明のエラー」ですが、どうやらフォーム上で用いたオブジェクトの解放の方法に問題があったようです。 今まで、想定しうる最大の個数ぶんを解放する命令を書いていまして・・・実際に作ったインスタンスの個数を越えて解放しようとしており、矛盾が起きていたようでした。 いろいろとありがとうございました。お騒がせして申し訳ありません。

  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.1

こんにちは。 具体的にはどんなソースを書かれていますか? 提示されても解決出来るかは解りませんが、、、

pythian
質問者

補足

お答えありがとうございます。Form2がメインフォームで、メニュー画面になっています。内容を選択すると、それに沿った内容でForm1のデザインが変わるようになっています。Form1と、それに配置されるコンポーネントは選択に応じてその都度生成されます。いままでは、Form1を終了させるとアプリケーションが終了するようしていたのですが、メニューに戻る必要が生じて、Form1を閉じるときに自身を破棄し、Formメニューから選択すると再び生成・・・ということがやりたいのです。 Form1に属するメンバを全て廃棄すれば良いんだと思っているのですが、上手くいかなくて・・・。(汗

関連するQ&A

  • EAccessViolationエラーの生成

    C++Builder 5.0でプログラムを作成しています。 Form1~Form3を作成し、Form1を自動生成の対象及びメインフォームとしました。Form1にはボタン1、Form2にはボタン2を用意し、ボタン1からはForm2を、ボタン2からはForm3を開くことが出来るようにしました。 Form1のボタン1には TForm2 *Form2 = new TForm2(Application); Form2->Show(); Form1->Hide();と記述し、 Form2のボタン2には TForm3 *Form3 = new TForm3(Application); Form3->ShowModal(); ← Form3はモーダルフォーム と記述しました。Form1とForm2のPublic部にint型の変数iとjを用意し、 Form3から Form1->i = 5; Form2->j = 5; という様に値を代入すると Form1の時はうまく代入できるのですが、Form2の変数に代入すると「Project1.exeがEAccessViolationクラスの例外を生成しました …」というエラーメッセージが表示されてしまいます。この原因は何でしょうか。なお、各フォームのヘッダファイルのインクルード はきちんと行っています。OSはWindows98です。御回答をどうかよろしくお願いします。

  • 《instantiate》(インスタンス化)と《create》(生成)

    《instantiate》(インスタンス化)と《create》(生成)が分かりません。 《instantiate》(インスタンス化)は、必要とする側の分類子の操作が、必要とされる側の分類子のインスタンスを生成することを示す。と書かれています。 《create》(生成)は、必要とする側の分類子が、必要とされる側の分類子のインスタンスを生成することを示す。と書かれています。よく分かりません。 JAVAでコーディングするとどのような感じになるのでしょうか? instantiateで検索していたら以下のようなコーディングが見つかりました。 public static class Commands { static Commands() { CloseCardCommand = new Command("CloseCard"); AddCardCommand = new Command("AddCard"); } public static Command CloseCardCommand { get; private set; } public static Command AddCardCommand { get; private set; } } このコーディングで、どのような処理をしているかも分かりません。 必要とする側の分類子の操作とは、Commandsでしょうか? 必要とされる側の分類子とは、CloseCardCommandとAddCardCommandでしょうか? 《create》(生成)の場合、どのようなコーディングになるのでしょうか? コンストラクタで CloseCardCommand = new Command("CloseCard"); AddCardCommand = new Command("AddCard"); と書くのではなく、クラス内(コンストラクタやメソッドの外)に書くのでしょうか? 宜しくお願いします。

    • ベストアンサー
    • Java
  • C#でのフォーム間のデータの受け渡しについて

    フォーム間のデータ(パラメータ等)の受け渡しについて教えてください。 現在Form1からForm2を起動させる場合、以下のようにForm2のインスタンスの生成時のパラメータを設定してもForm2のLoadイベントでは拾うことはできないのでしょうか? ↓実際のコード //Form1クラスのインスタンスを作成する //引数(a,b) Form2 f = new Form2(a,b); //Form1を表示する //ここではモーダルダイアログボックスとして表示する //オーナーウィンドウにthisを指定する f.ShowDialog(this); //フォームが必要なくなったところで、Disposeを呼び出す f.Dispose(); また、上記の方法が違っていた場合、方法としてどのようなやり方があるのか教えてください。 よろしくお願いいたします。

  • C#のフォーム間のイベント駆動

    C#悩んでおります。初心者です。 Form1とForm2があります。 Form1にはピクチャボックスが二つ並んでいて。 Form2にはチェックボックスが二つ並んでいます。 Form2のチェックボックスをオン-オフすると、それぞれのピクチャーのイメージを変更したいのですが、 なにせ、Form2の状況をForm1に知らせる方法がわかりません。 なにやら、デリゲートとイベントを使ってForm1に知らせるらしい、ということまではわかったのですが、具体的にどうやるのかわかりません。 いろいろネットで調べてはいるのですが、Form1,2が分かれていない例や、静的変数を使った例が多く、だめです。 静的だとイベントが発生しないので、イメージを更新するタイミングが無いですし、Form1,2が分かれていない場合を無理やりに分かれて記述すると、必ず記述のエラーが出ます。 どうすればいいのでしょうか?

  • vb2005 インスタンスの生成について

    vb2005で質問です Data.vbというグローバル変数を宣言しているモジュールファイルに以下の記述をします。   public x As SortedList(Of Integer, Integer)() = New SortedList(Of Integer, Integer)(1) {} 次にForm1.frmというファイルで、ある処理の中に以下の記述をします。  x(0) = New SortedList(Of Integer,Integer)  x(1) = New SortedList(Of Integer,Integer) ここで質問が2つあります。 1)なぜ2回もNEW句を使用しなければならないのでしょうか? 2)x(0)やx(1)について、宣言とインスタンスの生成を同時にする方法はありますか? ご回答よろしくお願い致します。

  • オブジェクト指向について質問

    メインのクラスをインスタンスする際にコンストラクターに書かれている処理が実行されますが、オブジェクトが生成された時のイベントに書くのと、どのような違いがありますか? public partial class Form1 : Form{ public Form1()//コンストラクター {処理1} private void Form1_Load(object sender, EventArgs e)//インスタンス時のイベント {処理2} } また、別クラスの中でnewを使ってインスタンスがされ場合、コンストラクターと上記のイベントは同じように発生しますか? public class Form2{ Form1 = new Form1(); } よろしくおねがいします。

  • newしないインスタンス?実体化しなくてもいいの?

    JAVAについて教えて下さい。 ServletContext application = getServletContext(); の成り立ちの意味なのですが、newがなぜないのか教えて下さい。 ~自身の考え~ (1)サーブレットコンテキストというクラスをインスタンス化して (サーブレットコンテキスト 変数A = new サーブレットコンテキスト();)     ↑                         ↑   クラス                       クラス (2)変数Aドットメソッド()によって、代入変数Bを作り上げる (サーブレットコンテキスト 代入変数B = 変数A . メソッド();) (3)のはずが、上記の式にはnewがありません。 なんで?? ~~ ~疑問点~ もしかしたらHttpServletでimportしているからそこでnewインスタンス化宣言している? だとするならどのような式になっているのでしょうか。 もしくはメソッドのF3キーとして上位をたどったときに出てきた public abstract class GenericServlet implements Servlet, ServletConfig, Serializable { public ServletContext getServletContext() { return getServletConfig().getServletContext(); } } として抽象クラスが出てきましたが、どこにもnew実体化していません。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • SetとNothingの存在意味?

    数値とオブジェクトの変数セットはそれぞれ、 Dim num as integer num = 5 Dim obj as Object set obj = new From set obj = Nothing ですが、 オブジェクトの場合でインスタンスを生成しない、単なる参照?別名? の場合はNothingは不要でしょうか? Dim obj as Object For x = 1 to 10 set obj = Form2 ' newとインスタンスを生成するのではなく、単なる参照  obj.Caption = str(x) & "回目" 'set obj = nothingは不要? Next x

  • attachMovieで生成したインスタンスへの文字代入

    FlashMX(AS1.0)を使用しています。 ダイナミックテキストを子にしたムービークリップのインスタンスをattachMovieで配置したのですが、ダイナミックテキストに文字列を代入しても文字のみが表示されません。 試しに、duplicateMovieClipでコピーした場合はダイナミックテキスト内の文字は表示されています。 スクリプトは以下のように組んでいます。 (略) 1:cnt++; 2:samp_mc = "tag"+cnt; 3:_root.attachMovie("sym_ln",samp_mc,cnt);//sym_ln...ダイナミックテキストを含んだシンボルのリンケージ 4:samp_mc.dymtxt = "123";//dymtxt...ダイナミックテキストの変数名 インスタンスを配置してもdymtxtに表示されません。が、 3:base_mc.duplicateMovieClip(samp_mc,cnt);//base_mc...ステージに配置したmcのインスタンス名 とすると表示されます。 attachMovieを使用してインスタンスを配置するようにしたいのですが、文字が表示されないのはどこに原因があるのでしょうか?

    • ベストアンサー
    • Flash
  • Objective-CでNSStringを複製

    ユーザが入力した文字列を、プログラムの内部データとして保持したいと考えています。 そこで、TextFieldを用意し、そこへ入力した文字を一旦別のクラスのメンバへ複製しようとしています。 保持するクラスにこんなメソッドを用意しました。 -(void) SetText( NSString* para) {   member = [[NSString alloc] initWiithString : para ]; } para で渡された文字列と同じ内容のインスタンスを生成して member で保持しようとしたわけです。 しかし、デバッガでstep実行すると、 member には para と同じアドレスが代入されます。 alloc と言っているので、C++ のnew のような動き(別インスタンスを生成)をイメージをしていたのですが、代入演算子と同じ動きをしていました。 そのため、para が release されてしまうと、この member から文字列を取り出せなくなってしまいます。 (解放済みオブジェクトにアクセスするので例外になります。当然ですけど) このほかには member = para; [member retain] とか、 member = [para copy]; などを試しましたが、いずれも一緒でした。 理由がわかる方、いらっしゃいましたら教えてください。 また、要は textFieldの文字列を別のviewに引き継ぐために、textField がrelease される前に保持したいのですけど、他に有効な方法を教えて頂けたら幸いです。

専門家に質問してみよう