はじめまして、宜しくお願い致します。
form間の値渡しで質問です。
たとえばform1のedit1に入力した値をform2で受け取り、
form2で別のボタンをクリックした時にその値を使って
form2のedit2と比較したいのですが
どうすればいいでしょうか?
調べたところ、useにunit名を追加すれば使えるとのことですが
できませんでした。
初歩的な事だと思いますので、簡単なキーワードでも結構です。
ご教授お願い致します。
どう記述してできませんでしたか?
form1の値を参照するのであれば、form1のインスタンスが必要。
単純に usesにunit1を追加したら使えるというものではない。
ただし、通常は自動生成されるフォームのため、グローバル変数が
宣言されていることから、usesするだけで参照することは可能。
implementation の上のほうに以下のような記述あるでしょう?
var
Form1: TForm1;
したがって、unit1をusesに追加しておけば、form2から、
form1.Edit1.Text のように参照可能である。
deldel(3号?)さん、初投稿のようですが...
↑こういう名前は誰でも思いつくようで^^; もっとユニークなものに変えた方がいいかと。
https://www.petitmonte.com/bbs/answers?question_id=3953
>form2で別のボタンをクリックした時にその値を使って
>form2のedit2と比較したいのですが
>調べたところ、useにunit名を追加すれば使えるとのことですが
自分で追加しなくても、form2のedit2のクリックイベントで、
if Form1.Edit1.Text = Edit2.Text then ShowMessage('同じ');
とか書けば、コンパイル時か実行時に「Form1への参照を追加する」とかいう
問い合わせがあって、自動的に usesのコードがソースに書き加えられるはずだけど。
ちょっぴり名前変えました。指摘ありがとうございます。
コードですがform1は
unit1(form1)にはeditボタンを用意して
その入力したものを数値に変換ということで下記
abcd := Edit1.Text;
efgh := StrToInt(abcd);
その数値をunit2(form2)で利用して比較するためにedit2を作成する
ということでform2のコードは下記となります
uses unit1;
procedure TForm2.btnClick(Sender: TObject);
var
form1:Tform1;
ijkl := Edit2.Text;
mnop := StrToInt(ijkl);
if (mnop= efgh) then 処理
こんな感じですが、このunit2の箇所まで進むとコンパイルエラーで
未定義の識別子efghと出ます。
はてはてさんと同意見です。
ただ自分はまだまだ初心者ですが^^;
ユニットを参照する時Usesは、implementationの下に書きます。
こうすると、循環参照エラーは出ません。
ファイル→ユニットを使う で、自動で追加されます。
あるいは、はてはてさんのご指摘されたように、
コード補完を利用して、実行ボタンを押して、
全自動で追加するか、になると思います。
以下は自分が試しに書いたサンプルです
implementationからコピペします。
//ユニット1
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
form2.Show;
end;
//ユニット2
implementation
uses Unit1;
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
if Form1.Edit1.Text = form2.Edit1.Text then
caption := '一致しました'//(elseの前に、;をつけるとエラーになります)
else //でなければ
caption := '一致しませんでした';
end;
書き込みすれ違いでしたね^^;
数値で比較されるんですね?
deldel3号かも知れないさんのと、同じ変数名で書いてみました。
//ユニット1
var
Form1: TForm1;
abcd:string;
efgh:integer;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
try//もし以下のコードにエラーがあれば (edit1が数値でなければ)
abcd := edit1.Text;//edit1の中身を変数abcdに代入
efgh := strtoint(abcd);//abcdの中身をInteger変数efghに代入
//efgh := strtoint(edit1.text);//でも大丈夫ですよ^^
form2.Show;
except//もしエラーなら
caption := '数値を入力してください';
end;
end;
//ユニット2
var
Form2: TForm2;
implementation
uses Unit1;
{$R *.dfm}
procedure TForm2.btnClick(Sender: TObject);
var
ijkl:string;
mnop:integer;
//↑で宣言した変数はブロック(begin end;間)内でしか使えません
begin
try//もし以下にエラーがあれば(edit1が数値でなければ)
ijkl := form2.Edit1.Text;//判りやすくする為にform2をつけてみましたそのままedit1.textでも大丈夫です。
mnop := strtoint(ijkl);
//mnop := strtoint(form2.edit1.text);//でも大丈夫ですよ
if efgh = mnop then
begin
//一致した場合ここが実行されます
caption := '一致しました';
end else begin
//一致しなかった場合ここが実行されます
caption := '一致しませんでした';
end;
except//もしエラーなら
caption := '数値を入力してください';
end;
end;
になります。
どうでしょうか?
はてはてさん、Delphi大好きさん本当に返信ありがとうございます。
ただ、まだ未解決です・・・。
変数の値を調べたところ、edit1のプロパティのtextに
4と入れているのでunit1の段階でabcd := edit1.Textのabcdには
文字列4が入ってほしいのですが、実際は空白が入っています。
これはtextに入れたものはabcd := edit1.Textという
書き方では4を返すのに間違った記述なのでしょうか?
問題は、どこで、何のコードが、変数を空白にしてしまうかですね。
代入の文法は間違っていないかと思いますよ?
あと、変数を他のUnitで使用するには? の、
グローバル変数は専用ユニットに さんの変数管理法を、
参考にしてみてはどうでしょうか?
これは自分も勉強させていただきました。
自分が先ほど書いた例には活かされて無いですが^^;;
試しに、
以下のタイマーを埋め込んではどうでしょうか?
var
Form1: TForm1;
abcd:string='0';//試しに最初から0を入れてみる
efgh:integer=0;
...
procedure TForm1.Timer1Timer(Sender: TObject);
begin
//これなら、どこで、何が動いて空白にされるか、解り易いと思います。
//Formの適当なところに、Timerイベントを作って以下を埋め込んでみてはどうでしょうか?。
//beepが少しうるさいですが^^;
//何かの参考になるかも知れません。
if abcd = '4' then
windows.Beep({音域}700,{長さ}300);
if abcd = '' then
windows.Beep(500,300);
if abcd = ' ' then
windows.Beep(500,300);
if abcd = '0' then
windows.Beep(400,300);
form1.caption := 'abcd' + abcd +' ' + 'efgh' + inttostr(efgh);
form2.caption := 'abcd' + abcd +' ' + 'efgh' + inttostr(efgh);
end;
変数宣言を、両方のユニットに記述している予感・・・
>こんな感じですが、このunit2の箇所まで進むとコンパイルエラーで
>未定義の識別子efghと出ます。
if (mnop= efgh) then 処理を
if (mnop= Form1.efgh) then 処理
~~~~~~
に変えてみたらどうなりますか?
>>みんみんさん
[DCC エラー] FORM1.PAS(529): E2003 未定義の識別子 : 'efgh'となりました。
次はDelphi大好きさんを参考にさせていただいて試してみます。
>>とおりすがりさん
変数宣言というのはabcd:stringやefgh:integerの部分ですよね?
Unit1で
var
Form1: TForm1;
abcd:string;
efgh:integer;
implementation
の箇所しかしていません。Unit2ではif (mnop= efgh) then の箇所にしか
efghは使用していません。
すみません。unit2でuseにunit1を宣言していませんでした。
ただ宣言したところコンパイルで[DCC エラー] UNIT2.PAS(15): F2047 'Unit2' の循環参照エラー
とでました。
何度も連続での書き込み申し訳ないです。
このusesはどちらのunitにimplementationの上と下で2箇所
もとから記述があるのですが、場所は関係あるのでしょうか?
どちらも下に記述すると[DCC エラー] FORM1.PAS(529): E2003 未定義の識別子 : 'efgh'となり、
unit2でimplementationの上に記述すると[DCC エラー] UNIT2.PAS(15): F2047 'Unit2' の循環参照エラーとなるようです。
教えていただいたunit1、unit2ともにimplementationの下にusesを書いた際のエラーが[DCC エラー] UNIT2.PAS(529): E2003 未定義の識別子 : 'efgh'
であるのでグローバル変数の宣言がうまくいってないのだと自分では
考えていますがどうでしょうか?
自分の場合ですが…。
コンパイラがご機嫌斜めでうまくいかない時・・・。
Delphiを二つ起動して、
ひとつを今開発している、うまくいかないソフト、
もうひとつを、不調と思われる部分を切り出したサンプル、
これを同時に編集し、色々試します。
そしてサンプルが成功したら、
メインと色々比較して違いを確かめます。
自分の場合ですが、
これで結構便利にやってます^^。
もしかするとそれが普通なのかもですが^^;
最悪、サンプルにメインのを移植して解決事する事も度々です^^;
直接のアドバイスではなくてごめんですが^^;
色々な参考書にも書かれているのですが、
コードの可読性の高い記述法、
これが、メンテナンスを含めたソフトを作るうえで、大切だそうです。
思わぬところにバグが潜んでしまうからだそうです。
参考になれば幸いです。
因みに自分も中々耳が痛い言葉です^^;
みなさん、ありがとうございました。
解決しました。方法としてはこういった形に
なります
unit2でif (mnop= efgh) then 処理を修正して
abcd:form1.Edit1.Text;
efgh:=StrToInt(abcd);
if (mnop= Form1.efgh) then 処理でうまくいきました。
みなさんの回答を元にコンパイルをいろいろ試して、
たどり着けました。とてもたすかりました。ありがとうございました。
うまくいかなった理由ですが、別のunitにedit5があったから
だと推測してます。
一応解決とさせていただきます。
ツイート | ![]() |