我有一个表格TForm1,其中我保留了cxSpreadsheet组件。我还创建了一个名为TTest的类。 TTest类包含两个用于加载数据的方法和另一个用于保存数据的方法。
当我在TTest类方法中调用TForm1类的方法时,即使创建了组件,当我调用Test.LoadMyData方法时它会给出访问冲突,它会给ATableView1变量提供访问冲突。
我做错了什么?
Uri imageUri = intent.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),imageUri);
Imageview imgview1 = (Imageview ) findViewById (R.id.imgview1);
imgeview1.setImageBitmap(bitmap);
答案 0 :(得分:3)
你陷入了混乱。 Delphi方法对隐式Self
对象(实例)进行操作。也称为方法调用的目标。如果我们使用Self
明确编写您的代码,那么它看起来像这样:
procedure TForm1.FormShow(Sender: TObject);
begin
Form1 := TForm1.Create(Self);
Self.Initilize;
Test := TTest.Create;
Test.LoadMyData;
end;
procedure TForm1.Initilize;
begin
Self.ATableView1 := Self.dxSpreadSheet1.Sheets[0] as TdxSpreadSheetTableView;
end;
procedure TForm1.LoadData;
begin
Self.ATableView1.Cells[10,1].SetText('Test Application');
end;
procedure TTest.LoadMyData;
begin
Form1.LoadData;
end;
正如您所看到的,您对Self
和Form1
的引用相当混乱。请注意,使用以下代码行在.dpr文件中实例化Form1
全局变量:
Application.CreateForm(TForm1, Form1);
最终会导致在FormShow
上调用Form1
。然后,您覆盖Form1
,现在有两个TForm1
个实例。您在Initilize
上致电Self
,然后在LoadData
上致电Form1
。
整件事情一团糟。代码可能如下所示:
// remove global variable Test
procedure TForm1.FormShow(Sender: TObject);
var
Test: TTest;
begin
Initilize;
Test := TTest.Create;
try
Test.LoadMyData(Self);
finally
Test.Free;
end;
end;
procedure TForm1.Initilize;
begin
ATableView1 := dxSpreadSheet1.Sheets[0] as TdxSpreadSheetTableView;
end;
procedure TForm1.LoadData;
begin
ATableView1.Cells[10,1].SetText('Test Application');
end;
procedure TTest.LoadMyData(Form: TForm1);
begin
Form.LoadData;
end;
我们将表单引用作为参数传递,而不是使用全局变量。
一旦掌握了这一点,您可以考虑完全删除全局变量Form1
。 IDE在假设每个表单只有一个实例的情况下创建此变量。但是没有必要这么做的理由。就个人而言,我认为通过删除这些全局变量,您将从长远来看受益。
答案 1 :(得分:3)
在你的问题中,你遗漏了一个非常重要的难题。您已经在评论中提到过它,但我在此重复一遍,因为它是您问题的直接触发因素。在评论中,您说表单创建如下:
with TForm1.Create(Self) do
begin
try
ShowModal;
finally
Free;
end;
end;
您的问题是,在ShowModal
的调用链中,您希望{em}专门为您刚刚创建的实例分配<{1}}。但显然你还没有做任何事情来设置Form1
。
您的解决方案&#34;是在Form1
调用链中分配Form1
。虽然这解决了你眼前的问题,但这远非正确,我将在后面解释原因。首先,我将展示一个完全避免问题的简单解决方案(请注意,它不是一个完整的解决方案,因为您的代码存在的问题远远超出您的意识)。
解决方案,摆脱 :
ShowModal
Vishal,试一试。如果你这样做,你会发现它有效。希望我现在全神贯注。你一开始并不相信,但也许你现在意识到我真的 做正确理解。
那我为什么要说你的解决方案&#34;错误?毕竟它似乎解决了这个问题....
嗯,你自己说过:你期望在
//This first line is the most important. //It explicitly sets which variable must be assigned to the new form. Form1 := TForm1.Create(Self); try Form1.ShowModal; finally Form1.Free; end;
开始时分配Form1
。你是对的,它应该是。通过在FormShow
内分配Form1 := Self;
,您只需修补之前的错误。当然,你同意修复原来的错误比仅仅修补它更好吗?
但是这里有一个更深层次的问题......我不确定你是否理解&#34;对象实例之间的区别&#34;和&#34;班级&#34;。 (如果你这样做,那么请继续阅读接下来的几段进行修订。)
您似乎期望在创建FormShow
时,它应自动分配给TForm1
变量。好像你期望在任何时间点内存中只有一个Form1
。但TForm1
是一种类型;这意味着它通常定义任意数量的相同类型的对象实例的行为。每次创建TForm1
时,它都是表单的新单独实例。每个实例都可以拥有自己的变量。 E.g。
TForm1
考虑一下您的错误&#34;解决方案会发生什么?#34;如果你需要2个表格变量?你会在JohnsForm1 := TForm1.Create(Self);
PaulsForm1 := TForm1.Create(Self);
方法中写些什么? FormShow
或 JohnsForm1 := Self;
?
当然,你仍然可以选择,一次只在内存中保留一个PaulsForm1 := Self;
个实例。但是Delphi没有办法自动知道你的意图。所以你仍然应该如上所述明确地做任何所需的任务。
我提到你的代码还有更严重的问题。它与上面关于对象实例和类类型的讨论有关。
你的TForm1
课程做了一系列不必要的假设:
TTest
的一个实例。TForm1
变量。同样,如果您需要Form1
和JohnsForm1
,您的代码将无法正常使用。
PaulsForm1
和TTest.LoadMyData
的微小变化解决了这些问题。
TForm1.FormShow
为了记录,David已经在his answer中向您提供了此信息。他的回答也证明了对新//Write LoadMyData so it can be told which form instance to load the data into
procedure TTest.LoadMyData(ALoadForm: TForm1);
begin
ALoadForm.LoadData;
end;
//Change FormShow to tell Test which form to use in LoadMyData
procedure TForm1.FormShow(Sender: TObject);
begin
Initilize;
Test := TTest.Create;
Test.LoadMyData(Self);
end;
实例的适当资源保护,而我为了简单起见将其排除在外。
顺便说一句,这两个小小的改变也可以解决你的问题 基本上,您的代码中有2个错误。两个错误的结合导致了你的问题 您可以修复其中任何一个以解决问题。但你应该解决这两个问题,以使你的代码更好。
答案 2 :(得分:0)
大卫如此雄辩地说,这是你创造的混乱。他说,IDE在项目文件中插入一行自动为您创建表单是正确的。因此,自己创建它是多余的。
在这个实例中,OnShow处理程序可能是向网格添加一些测试数据的正确位置,但我不打算使用TTest类来执行此操作。也就是说,首先让逻辑工作,然后根据需要将这些东西移到另一个类中。我建议这是因为你似乎没有很好地掌握如何做OOD。我们一次都在那里!首先简化事情。
我为CodeRage 9制作了一个你可能感兴趣的视频。它被称为“你最近拥抱过你的内部软件管道工吗?”在YouTube上搜索它。它会让你对这个一般主题(可能太多)有所了解。
答案 3 :(得分:-10)
type
TForm1 = class(TForm)
dxSpreadSheet1: TdxSpreadSheet;
procedure FormShow(Sender: TObject);
public
ATableView1 : TdxSpreadSheetTableView;
procedure Initilize;
procedure LoadData;
end;
TTest = class
public
procedure SaveMyData(MyValue : String);
procedure LoadMyData;
end;
var
Form1: TForm1;
Test: TTest;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
begin
//Form1 is nil, if I check before executing below statement.
Form1 := Self; //This statement make my code work. mmmhhhhhaaaa Love This Statement.
Initilize;
Test := TTest.Create;
Test.LoadMyData;
end;