Sign in Join
Wiki copytemporary

Form Tutorial/zh CN: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11一个在 Lazarus 中使用窗体的简短介绍。
22
33## 窗体是什么?
44
55The form (class [[TForm]]) represents a window or dialog box that is the user interface of an [[Application|application]]. It is the container on which all other [[LCL Components|components]] (e.g. buttons, labels, edit fields, images, etc.) are inserted .
66
77## 第一个GUI应用程序
88
99Upon successfully installing Lazarus and starting a new Application Project, an empty form is created. Otherwise you can create a new [[Overview of Free Pascal and Lazarus|GUI application]] under Main menu -\> Project -\> New Project -\> Application OK.
1010
1111Now you have created a new, fully functional project with a form:
1212
13-<figure>
14-<img src="Form1_Designmodus.png" title="Form1_Designmodus.png" />
15-<figcaption>Form1_Designmodus.png</figcaption>
16-</figure>
13+![](/wiki-images/7/73/Form1_Designmodus.png)
1714
18-To run the newly created project, you can simply press the <span class="kbd">F9</span> key or click with the mouse on the main menu icon ![](/wiki-images/b/b8/Start.png) (or Main menu: Run -\> Run). The project will be compiled and executed.
15+To run the newly created project, you can simply press the `F9` key or click with the mouse on the main menu icon ![](/wiki-images/b/b8/Start.png) (or Main menu: Run -\> Run). The project will be compiled and executed.
1916
2017Nothing really exciting happens. The form (Form1) changes slightly in appearance and the points from the raster grid (help for positioning of individual components) disappear (as long as the grid points are visible, you also know that it is still in design mode):\
2118![](/wiki-images/7/73/Form1_Designmodus.png) -\> ![](/wiki-images/d/dc/Form1_Runmodus.png)
2219
2320Next, you can place a [[TButton]] onto the form. This will be used later to allow the opening of a second form:
2421
2522Select the TButton from the [[Standard tab]] on the [[Component Palette]].
2623
27-<figure>
28-<img src="TButtonStandardpalette.png" title="TButtonStandardpalette.png" />
29-<figcaption>TButtonStandardpalette.png</figcaption>
30-</figure>
24+![](/wiki-images/4/49/TButtonStandardpalette.png)
3125
3226and click on the form: There is now a button placed on Form1 with the name and caption "Button1".
3327
3428In order for this button to do something, you have to announce that you intend to do something when you click it. This can be regarded as a simple event. For this you need an [[Event order|event handler]] that is called after the click. The event handler for a mouse click can be quite easily reached by double-clicking on Button1 (or in the Object Inspector, select Button1 -\> Events tab -\> OnClick, then click on the \[...\] button). This creates a procedure TForm1.Button1Click in the code editor, which is always called (at [[runtime]], not in design time) when Button1 is clicked:
3529
36-<figure>
37-<img src="NeuesProjekt2.png" title="NeuesProjekt2.png" />
38-<figcaption>NeuesProjekt2.png</figcaption>
39-</figure>
30+![](/wiki-images/9/9b/NeuesProjekt2.png)
4031
4132To make the application do something after clicking on Button1, add some code between the [[Begin]] and [[End]] of the procedure TForm1.Button1Click like this:
4233
4334``` pascal
4435procedure TForm1.Button1Click(Sender: TObject);
4536begin
4637 Caption:='My first Form'; //Caption of Form1 is changed (text in formhead)
4738 //or
4839 Button1.Caption:='Hello'; //Caption of button is changed (shown text of button)
4940end;
5041```
5142
52-Now run the form by pressing <span class="kbd">F9</span>, and notice that when the button is clicked the form caption and the button caption both change.
43+Now run the form by pressing `F9`, and notice that when the button is clicked the form caption and the button caption both change.
5344
5445You can now experiment a little bit and learn how to use the standard components. To get started, I would recommend you to try samples of the following components:
5546
56-<table>
57-<tbody>
58-<tr>
59-<td><p>[[TButton]]</p></td>
60-<td><figure>
61-<img src="tbutton.png" title="tbutton.png" />
62-<figcaption>tbutton.png</figcaption>
63-</figure></td>
64-</tr>
65-<tr>
66-<td><p>[[TLabel]]</p></td>
67-<td><figure>
68-<img src="tlabel.png" title="tlabel.png" />
69-<figcaption>tlabel.png</figcaption>
70-</figure></td>
71-</tr>
72-<tr>
73-<td><p>[[TEdit]]</p></td>
74-<td><figure>
75-<img src="tedit.png" title="tedit.png" />
76-<figcaption>tedit.png</figcaption>
77-</figure></td>
78-</tr>
79-<tr>
80-<td><p>[[TMemo]]</p></td>
81-<td><figure>
82-<img src="tmemo.png" title="tmemo.png" />
83-<figcaption>tmemo.png</figcaption>
84-</figure></td>
85-</tr>
86-<tr>
87-<td><p>[[TToggleBox]]</p></td>
88-<td><figure>
89-<img src="ttogglebox.png" title="ttogglebox.png" />
90-<figcaption>ttogglebox.png</figcaption>
91-</figure></td>
92-</tr>
93-<tr>
94-<td><p>[[TCheckBox]]</p></td>
95-<td><figure>
96-<img src="tcheckbox.png" title="tcheckbox.png" />
97-<figcaption>tcheckbox.png</figcaption>
98-</figure></td>
99-</tr>
100-<tr>
101-<td><p>[[TRadioButton]]</p></td>
102-<td><figure>
103-<img src="tradiobutton.png" title="tradiobutton.png" />
104-<figcaption>tradiobutton.png</figcaption>
105-</figure></td>
106-</tr>
107-<tr>
108-<td><p>[[TListBox]]</p></td>
109-<td><figure>
110-<img src="tlistbox.png" title="tlistbox.png" />
111-<figcaption>tlistbox.png</figcaption>
112-</figure></td>
113-</tr>
114-<tr>
115-<td><p>[[TComboBox]]</p></td>
116-<td><figure>
117-<img src="tcombobox.png" title="tcombobox.png" />
118-<figcaption>tcombobox.png</figcaption>
119-</figure></td>
120-</tr>
121-<tr>
122-<td><p>[[TScrollBar]]</p></td>
123-<td><figure>
124-<img src="tscrollbar.png" title="tscrollbar.png" />
125-<figcaption>tscrollbar.png</figcaption>
126-</figure></td>
127-</tr>
128-</tbody>
129-</table>
47+| | |
48+|----|----|
49+| [[TButton]] | ![](/wiki-images/b/b2/Tbutton.png) |
50+| [[TLabel]] | ![](/wiki-images/a/a2/Tlabel.png) |
51+| [[TEdit]] | ![](/wiki-images/d/db/Tedit.png) |
52+| [[TMemo]] | ![](/wiki-images/1/1b/Tmemo.png) |
53+| [[TToggleBox]] | ![](/wiki-images/1/15/Ttogglebox.png) |
54+| [[TCheckBox]] | ![](/wiki-images/d/d6/Tcheckbox.png) |
55+| [[TRadioButton]] | ![](/wiki-images/7/7a/Tradiobutton.png) |
56+| [[TListBox]] | ![](/wiki-images/7/77/Tlistbox.png) |
57+| [[TComboBox]] | ![](/wiki-images/7/75/Tcombobox.png) |
58+| [[TScrollBar]] | ![](/wiki-images/c/c4/Tscrollbar.png) |
13059
13160There is additional helpful information in the [[Lazarus Tutorial]].
13261
13362## 第二个窗体的使用
13463
13564这篇教程显示如何在一个工程中使用多个窗体。在这个示例中,仅仅两个窗体,Form1 (主窗体)和 Form2,被创建,but the process is identical for additional forms.
13665
13766There is a main form with a button, which when clicked opens the new form. The new form also receives a button which when clicked closes the new form and returns you to the main form.
13867
13968If you have worked through the first tutorial [[Form Tutorial|The first GUI app]], you will need to delete the code between the begin and end of procedure TForm1.Button1Click. Otherwise you will need to create a new project (application), drop a button on the form, and create the OnClick event handler for this Button1.\
14069Click the new button to enter a caption (visible text on the button). To do this, select the button (just click it once) and in the Object Inspector click Properties -\> Caption, and enter the text "Open Form2".
14170
142-<figure>
143-<img src="Objektinspektor.png" title="Objektinspektor.png" />
144-<figcaption>Objektinspektor.png</figcaption>
145-</figure>
71+![](/wiki-images/5/52/Objektinspektor.png)
14672
14773In the Main menu click File -\> New Form, to add a second form (Form2) to the project. Place a button (Button1) on Form2 and create the OnClick event handler for it. Change the caption of this button to "Close".
14874
149-Now the project has two forms, each of which can be selected and displayed with Main menu Project -\> Forms (or key combination <span class="kbd">Shift</span> + <span class="kbd">F12</span>). Alternatively, you can select the tab for a Unit in the Source Editor, then use <span class="kbd">F12</span> to switch between the code editor and form designer for the form of the associated [[Unit]].
75+Now the project has two forms, each of which can be selected and displayed with Main menu Project -\> Forms (or key combination `Shift` + `F12`). Alternatively, you can select the tab for a Unit in the Source Editor, then use `F12` to switch between the code editor and form designer for the form of the associated [[Unit]].
15076
15177In the [[source code editor]], go to the Form1 associated [[Unit]] (Unit1) and add "Unit2" to the [[Uses]] clause:
15278
15379``` pascal
15480uses
15581 Classes, SysUtils, ... , Unit2; // It is important that the individual units are separated by a comma(,)
15682 // and the uses clause ends with a semicolon(;).
15783```
15884
15985Now you can call Unit2 (and thus Form2) from Unit1.
16086
16187Next, edit the OnClick event of the button belonging to Form1:
16288
16389``` pascal
16490unit Unit1;
16591...
16692procedure TForm1.Button1Click(Sender: TObject);
16793begin
16894 Form2.ShowModal; //Displays Form2, the focus is placed on Form2.
16995end;
17096```
17197
17298``` pascal
17399unit Unit2;
174100...
175101procedure TForm2.Button1Click(Sender: TObject);
176102begin
177103 Close; //Close Form2.
178104end;
179105```
180106
181-Now you can start the project (![](/wiki-images/b/b8/Start.png) or <span class="kbd">F9</span>) and open Form2 by clicking the button on Form1.
107+Now you can start the project (![](/wiki-images/b/b8/Start.png) or `F9`) and open Form2 by clicking the button on Form1.
182108
183109### Difference between Show and ShowModal
184110
185111Both methods *Show* and *ShowModal* make a form visible. To see the difference between *Show* and *ShowModal*:
186112
187113- Extend the previous example [[Form Tutorial|The use of a second form]] by adding a second TButton to *Form1*.
188114- Select *Button1* and change the properties *Name* to *btnShow* and *Caption* to *Show*.
189115- Select *Button2* and change the properties *Name* to *btnShowModal* and *Caption* to *ShowModal*.
190116- Create (or modify) the *OnClick* event handler of the two buttons as follows:
191117
192118``` pascal
193119procedure TForm1.btnShowClick(Sender: TObject);
194120begin
195121 Form2.Show;
196122 ShowMessage('Form2 is opened!');
197123end;
198124
199125procedure TForm1.btnShowModalClick(Sender: TObject);
200126begin
201127 Form2.ShowModal;
202128 ShowMessage('Form2 is opened and closed again!');
203129end;
204130```
205131
206132- Start and watch the difference!
207133
208134Show
209135
210136This procedure makes a form visible and continues to execute the code of the calling control (*Form1*). In our example, the message ([[Dialog Examples|ShowMessage]]) appears almost simultaneously with *Form2*. You can also continue to use the calling form *Form1*. For example, it is possible to move it, or click the *Show* button again (but clicking *ShowModal* will cause an error).
211137
212138Instead of using **`<myForm>.Show;`**, it is also possible to use **`<myForm>.Visible:=True;`**. The method *Show* does the following:
213139
214140``` pascal
215141procedure TCustomForm.Show;
216142begin
217143 Visible := True;
218144 BringToFront;
219145end;
220146```
221147
222148The only difference between **`<myForm>.Show;`**, and **`<myForm>.Visible:=True;`** is that the form displayed using *Show* will be on top of all other forms currently displayed.
223149
224150ShowModal
225151
226152*ShowModal* halts the processing of code in the calling control (*Form1*) until the newly opened form (*Form2*) has been closed. In the example, the *ShowMessage* line immediately following *ShowModal* is executed only after *Form2* is closed. The calling form is frozen: You can neither move *Form1* nor click any of its buttons.
227153
228154ShowModal is a function that returns an integer result, see [[doc:lcl/forms/tmodalresult.html|TModalResult]]. The returned value allows branching based on how the form was closed.
229155
230156## 两个窗体能够互相调用
231157
232158It is generally good program design to avoid calling the main form from a second form. It is better to return to the main form by closing the second form (as in the previous example) and letting focus revert to the main form. It is, however, possible to call the main from from a sub-form, as this example will show.
233159
234160In order for Form1 to call Form2, Unit1 must have Unit2 in its Uses clause. Conversely, for Form2 to call Form1, Unit2 must have Unit1 in its Uses clause. This leads to a potential Circular Unit Reference compiler error, with each Unit referring to the other. This example also shows how to avoid the Circular Unit Reference error.
235161
236162To set up this example, either modify the forms from the previous example ([[Form Tutorial|The Use of a Second Form]]), or create a new project with two forms, each having a single button. Set the caption of Form1.Button1 to "Open Form2", and set the caption of Form2.Button1 to "Open Form1".
237163
238164如果你正在修改先前的示例,在Unit1中的Uses分句中移除"Unit2"。
239165
240166Add a Uses clause to the [[Implementation]] section of each [[Unit]]. Add Unit2 to the Unit1 clause, and add Unit1 to the Unit2 clause, as below:
241167
242168``` pascal
243169unit Unit1;
244170...
245171implementation
246172
247173uses
248174 Unit2;
249175...
250176```
251177
252178``` pascal
253179unit Unit2;
254180...
255181implementation
256182
257183uses
258184 Unit1;
259185...
260186```
261187
262188Now change the code located behind the OnClick event of the button event handler:
263189
264190``` pascal
265191unit Unit1;
266192...
267193procedure TForm1.Button1Click(Sender: TObject);
268194begin
269195 Form2.Show;
270196end;
271197```
272198
273199``` pascal
274200unit Unit2;
275201...
276202procedure TForm2.Button1Click(Sender: TObject);
277203begin
278204 Form1.Show;
279205end;
280206```
281207
282208## Passing Variables to Other Forms
283209
284210In accordance with the above example [[Form Tutorial|The Use of a Second Form]], it is possible to declare a [[Global variables|global variable]] in the interface part of Unit2. This would allow access in both Unit1 and Unit2 to one and the same [[Variable|variable]] (This is because by putting Unit2 in the Uses clause of Unit1, all variables declared in the interface part of Unit2 are also available in Unit1). This practice should be limited to a minimum, as it quickly becomes difficult to remember which individual variables are in scope, potentially increasing errors. It is better to use [[Local variables|local variables]], define a [[Object Oriented Programming with Free Pascal and Lazarus|Property]] in a [[Class]] or, alternatively, as a variable in a class.
285211
286212In the next project, a second form is opened by clicking on the button. In this case, in the unit of the main form is counted how often the second shape has been shown. In this second form you can ask to see by clicking on the button, how often it has been opened:
287213
288214- a new project with two forms, each a button on it and their OnClick events to evaluate.
289215- now, in the public part of the [[Class]] TForm2 (Unit2) a variable (in this case a [[Const|constant]], which we defined as variable abuse) of type integer with the name Count create:
290216
291217``` pascal
292218unit Unit2;
293219...
294220 TForm2 = class(TForm)
295221 Button1: TButton;
296222 procedure Button1Click(Sender: TObject);
297223 private
298224 { private declarations }
299225 public
300226 { public declarations }
301227 const Count: Integer = 0; //here
302228 end;
303229```
304230
305231- now even customize the Button event handler accordingly:
306232
307233``` pascal
308234unit Unit1;
309235...
310236procedure TForm1.Button1Click(Sender: TObject);
311237begin
312238 inc(Form2.Count); //Increase the counter by 1 on each call to Form2
313239 Form2.ShowModal;
314240end;
315241```
316242
317243``` pascal
318244unit Unit2;
319245...
320246procedure TForm2.Button1Click(Sender: TObject);
321247begin
322248 ShowMessage('Form2 would be displayed '+IntToStr(Count)+' times');
323249end;
324250```
325251
326252In this way you can in Unit1 access all public variables/properties/functions/procedures (general methods) of Unit2.
327253
328254## Other Form-Related Subjects
329255
330256### Use Another Form as the Main Form
331257
332258If you determine after a while that you want to have displayed rather a different form or new form for the view at startup, you can under the main menu Project -\> Project Options -\> Forms:
333259
334-<figure>
335-<img src="Projekteinstellungen_Formulare.png" title="Projekteinstellungen_Formulare.png" />
336-<figcaption>Projekteinstellungen_Formulare.png</figcaption>
337-</figure>
260+![](/wiki-images/7/76/Projekteinstellungen_Formulare.png)
338261
339262Alternatively, you can display, in Mainmenu -\> Project -\> Show .lpr file, that Project.lpr (Pascal code of the main program) and create the first form to be displayed as the first:
340263
341264``` pascal
342265program Project1;
343266...
344267 Application.CreateForm(TForm2, Form2); //Form2 is created in first and shown when the application starts
345268 Application.CreateForm(TForm1, Form1);
346269```
347270
348271### Save properties of the shape at end of program
349272
350273- [[Remember form position and size|Remember form position and size#Using_TForm.SessionProperties and TXMLPropStorage]]
351274
352275## Generate the form dynamically
353276
354277### Create a Lazarus designed form dynamically
355278
356279You do not have to create all the forms that may be called during the term of an application at startup. Some developers generally keep none of it and delete the code automatically created when you insert a new form in a project from the Projekt.lpr out immediately. If you want to write a library that contains a couple of GUIs, you can not get around the dynamic creation of forms.
357280
358281An example:
359282
360283- new application with two forms, Form1 a button (add "Unit2" in the uses clause of unit1)
361284- open the Projekt.lpr (Project -\> lpr file.)
362285- delete the line "Application.CreateForm(TForm2, Form2);"
363286- in the OnClick event of Button1, Form1 add following code:
364287
365288``` pascal
366289procedure TForm1.Button1Click(Sender: TObject);
367290begin
368291 Form2:=TForm2.Create(Nil); //Form2 is created
369292 Form2.ShowModal; //Form2 is displayed
370293 FreeAndNil(Form2); //Free Form2
371294end;
372295```
373296
374297- now simply start
375298
376299### Creating a new form dynamically
377300
378301The following example will demonstrate how new forms can be generated in code, without using the Form Designer,.
379302
380303In this example clicking a button should open another form that itself contains a button. Clicking this second button makes a message appear warning that the form will close; then the form is closed.
381304
382305- Create a new application with a form and a button
383306- In the OnClick event of Button1, in Form1, add the following code:
384307
385308``` pascal
386309procedure TForm1.Button1Click(Sender: TObject);
387310var
388311 MyForm: TForm;
389312 MyButton: TButton;
390313begin
391314 MyForm:=TForm.Create(nil);
392315 MyForm.SetBounds(100, 100, 220, 150);
393316 MyForm.Caption:='My dynamic created form';
394317
395318 MyButton:=TButton.create(MyForm);
396319 MyButton.Caption:='Close my form';
397320 MyButton.SetBounds(10, 10, 200, 30);
398321 MyButton.Parent:=MyForm;
399322
400323 MyButton.OnClick:=@MyButtonClick;
401324
402325 MyForm.ShowModal;
403326
404327 FreeAndNil(MyForm);
405328end;
406329```
407330
408331> **Note:** If a component has been created with an owner (TButton.Create(Owner: TComponent)), it belongs to the owner, who is then responsible to free the component. Thus MyButton is freed automatically by freeing MyForm.
409332
410333- now the event handler for MyButton.OnClick must be created. To this end, write in the private section of class TForm1 the following procedure declaration:
411334
412335``` pascal
413336TForm1 = class(TForm)
414337...
415338private
416339 { private declarations }
417340 procedure MyButtonClick(Sender: TObject);
418341```
419342
420-- press <span class="kbd">Ctrl\]</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span> (code completion) and insert the following code as the handler implementation:
343+- press `Ctrl]`+`Shift`+`C` (code completion) and insert the following code as the handler implementation:
421344
422345``` pascal
423346procedure TForm1.MyButtonClick(Sender: TObject);
424347begin
425348 Showmessage('Attention, closing my dynamically created form!');
426349 if Sender is TButton then
427350 TForm(TButton(Sender).Parent).Close;
428351end;
429352```
430353
431354- now the project can be compiled and executed
432355
433356## See also
434357
435358- [[LCL Tips|Tips for manual generation of controls]]
436359- [[LCL Tips|Example to create a complete GUI application by code]]
437360- [[Testing, if form exists]]
438361- [[Canvas draw vertical line on form/de]]
439362- [[Drawing with canvas]] on form
440363- [[user should not be able to close form]]
441364- [[LCL Tips|Creating a non-rectangular window or control]]
442365- [[Remember form position and size]]
443366
444367## 贡献者和更改
445368
446369- 简体中文版本由 robsean 于 2020-01-20 创建。
447370
448371---
449372*From the Free Pascal wiki, page "Form Tutorial/zh CN", as it stood on 2020-02-15 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
450373Category: Code
451374Category: Forms
452375Category: LCL
453376Category: Tutorials

Back to history