At the latest when you start another window F1 from a (main) window FMain, the question might have to be answered according to which concept the data transfer between the two application windows should take place. The following considerations will certainly enter into the concept:
In the following sections, you will find chapters in which the data transfer for the above considerations has already been described.
You can give start values to the window F1 with an appropriately designed constructor via mandatory and optional parameters in the _new method → Chapter 12.2.7.1 Project 1. Another possibility is offered by self-developed dialogues → Chapter 24.3.4 Account.Manager.
You can also consider moving data from control elements to FMain and F1 via the Drag&Drop methods as a data transfer.
In a real, tested project, the temperature is recorded via a temperature sensor on a circuit board via an RS232 interface in an application window FSensor. From a main window FMain, the temperature reading is accessed on FSensor and the temperature is displayed in FMain:
Figure 12.2.9.3.1: Temperature display on FMain - next to it FSensor
So that you can follow the project, the temperature values are generated by a random generator in a certain temperature range. This eliminates the need for a real board and the class SerialPort (gb.net).
If you want to access properties and methods of control elements on FMain and FSensor alternately, you must set the property Public of the respective control elements to True at development time, in addition to the declaration of project-wide variables. This is not possible at runtime because the Public property is virtual. As already noted in → Chapter 12.2.0 'Form - Window class and Form class', the following applies: As long as there is no compelling reason to change the Public property from False to True, you should give preference to the complete encapsulation of the state and behaviour of objects.
On the other hand, the bidirectional data exchange between FMain and FSensor via the public control elements and variables is very simple. The source code for the classes FMain and FSensor in projects 1 and 2 is sufficiently short and is therefore given in full.FMain.class
' Gambas class file Public Sub Form_Open() Application.MainWindow = FMain FMain.Center() FMain.Resizable = False piboxOn.Picture = Picture["LED/led_yellow.svg"] ValueBox1.Value = 0.2 btnStartSensor1.Text = "Start temperature measurement sensor 1". End Public Sub btnStartSensor1_Click() piboxOn.Picture = Picture["LED/led_green.svg"] FSensor.fTIBegin = 22.9 FSensor.fTIEnd = 24 FSensor.fTITrigger = ValueBox1.Value FSensor.Show() FSensor.X = FMain.X + FMain.W + 20 FSensor.Y = FMain.Y + FMain.H - FSensor.H btnStartSensor1.Enabled = False End Public Sub ValueBox1_Change() If ValueBox1.Value >= 0 And If ValueBox1.Value <= 0.9 Then FSensor.fTITrigger = ValueBox1.Value End Public Sub Form_Close() FMain.Close() End </close> FSensor.class <code gambas> ' Gambas class file Public fCurTemperature As Float Public fTIBegin As Float Public fTIEnd As Float Public fTITrigger As Float Private fSavedTemperature As Float Public Sub Form_Open() FSensor.Center() FSensor.Resizable = False TimerSimulation.Trigger() End Public Sub TimerSimulation_Timer() Dim bChanged As Boolean Randomize fCurTemperature = Rnd(fTIBegin, fTIEnd) bChanged = Abs(fCurTemperature - fSavedTemperature) > fTITrigger fSavedTemperature = fCurTemperature If bChanged Then FMain.lblTemperaturAnzeige.Text = Format(FSensor.fCurTemperature, "##.0 °C") Endif End Public Sub Form_Close() FMain.piboxOn.Picture = Picture["LED/led_yellow.svg"] ' piboxOn.Public = True FMain.btnStartSensor1.Enabled = True ' btnStartSensor1.Public = True FMain.lblTemperaturAnzeige.Text = "--- °C" ' lblTemperaturAnzeige.Public = True FMain.ValueBox1.Value = 0.2 ' ValueBox1.Public = True End
Comment:
In the second project, data exchange between the application windows FMain and FSensor takes place only via public interfaces whose signatures are known. Each class thus completely encapsulates its data vis-à-vis the other class. This is also clear in the source code for the two classes FMain and FSensor: there are no public control elements and also no public variables!
FMain.class ' Gambas class file Private fTITrigger As Float = 0.2 Public hSensor As FSensor Public Sub Form_Open() Application.MainWindow = FMain FMain.Center() FMain.Resizable = False piboxOn.Picture = Picture["LED/led_yellow.svg"] ValueBox1.Value = fTITrigger End Public Sub btnStartSensor1_Click() CreateSensor1() piboxOn.Picture = Picture["LED/led_green.svg"] btnStartSensor1.Enabled = False End Public Sub Sensor1_Close() piboxOn.Picture = Picture["LED/led_yellow.svg"] btnStartSensor1.Enabled = True lblTemperature1.Text = "--- °C" ValueBox1.Value = fTITrigger End Public Sub Sensor1_Change() lblTemperature1.Text = Format(hSensor.Temperature, "##.0 °C") End Public Sub ValueBox1_Change() If hSensor Then If ValueBox1.Value >= 0 And If ValueBox1.Value <= 0.9 Then hSensor.TriggerValue = ValueBox1.Value Endif Endif End Public Sub CreateSensor1() Dim hObserver As Observer Dim aRanges As Float[] = [19.9, 21] hSensor = New FSensor(aRanges[0], aRanges[1]) hSensor.Caption = "TEMPERATUR-SENSOR 1" hSensor.TriggerValue = fTITrigger hSensor.Show() hSensor.X = FMain.X + FMain.W + 20 hSensor.Y = FMain.Y + FMain.H - hSensor.H hObserver = New Observer(hSensor) As "Sensor1" End Public Sub Form_Close() FMain.Close() End
FSensor.class
' Gambas class file Private fSavedTemperature As Float = 0.0 Private $fIBegin As Float Private $fIEnd As Float '-------------------------------------------------------------------- '' Property: Temperature, Access right: public, Modus: read-only Property Read Temperature As Float '' Property: TriggerValue, access right: public Property TriggerValue As Float '--------------------------------------------------------------------- Private $fTemperature As Float ' Local variable ➘ Cut point Private $fTriggerValue As Float ' Local variable ➘ Cut point '--------------------------------------------------------------------- '' Event: Change Event Change '--------------------------------------------------------------------- Public Sub _new(IBegin As Float, IEnd As Float) If Not TypeOf(IBegin) = gb.Float Then Error.Raise("Type error: Start value of temperature interval.") If Not TypeOf(IEnd) = gb.Float Then Error.Raise("Type error: end value of temperature interval.") If IBegin >= IEnd Then Error.Raise("The start value is greater than or equal to the end value of the interval..") $fIBegin = IBegin $fIEnd = IEnd End Public Sub Form_Open() Me.Center() Me.Resizable = False TimerSimulation.Delay = 1000 TimerSimulation.Start() TimerSimulation.Trigger() End ' Form_Open() Public Sub TimerSimulation_Timer() Dim bChanged As Boolean Randomize $fTemperature = Rnd($fIBegin, $fIEnd) bChanged = Abs($fTemperature - fSavedTemperature) > $fTriggerValue fSavedTemperature = $fTemperature If bChanged Then Raise Change End ' Additional service or interface (public method): Temperature_read Private Function Temperature_Read() As Float Return $fTemperature End ' Additional service or interface (public method): Trigger_read Private Function TriggerValue_Read() As Float Return $fTriggerValue End ' Additional service or interface (public method): Trigger_Write Private Sub TriggerValue_Write(Value As Float) If Value < 0 Or Value > 1 Then Error.Raise("The trigger value is not in the interval. [0|1]") Endif $fTriggerValue = Value End
Comment:
Public Sub TimerSimulation_Timer() Dim bChanged As Boolean Randomize $fTemperature = Rnd($fIBegin, $fIEnd) bChanged = Abs($fTemperature - fSavedTemperature) > $fTriggerValue fSavedTemperature = $fTemperature If bChanged Then Raise Change End Public Sub Sensor1_Change() lblTemperature1.Text = Format(hSensor.Temperature, "##.0 °C") End
Public Sub Sensor1_Close() piboxOn.Picture = Picture["LED/led_yellow.svg"] btnStartSensor1.Enabled = True lblTemperature1.Text = "--- °C" ValueBox1.Value = fTITrigger End
FSensor.class:
Public Sub _new(IBegin As Float, IEnd As Float) If Not TypeOf(IBegin) = gb.Float Then Error.Raise("Type error: Start value.") If Not TypeOf(IEnd) = gb.Float Then Error.Raise("Type error: End value of temperature interval.") If IBegin >= IEnd Then Error.Raise("The start value is greater than or equal to the end value.).") $fIBegin = IBegin $fIEnd = IEnd End
FMain.class:
Public Sub CreateSensor1() Dim hObserver As Observer Dim aRanges As Float[] = [19.9, 21] hSensor = New FSensor(aRanges[0], aRanges[1]) hSensor.Caption = "TEMPERATURE-SENSOR 1" hSensor.TriggerValue = fTITrigger hSensor.Show() hSensor.X = FMain.X + FMain.W + 20 hSensor.Y = FMain.Y + FMain.H - hSensor.H hObserver = New Observer(hSensor) As "Sensor1" End
The observer must be created because the FSensor class inherits from the Form class but does not have the extensions (2 properties and an event) of the class 'in view'.
In my opinion, the project offers several advantages over project 1:
The advantages sound convincing. The only thing is that you will soon realise that these advantages quickly melt away in larger projects, because encapsulating a class consistently and neatly can be very difficult and tedious in design. Occasionally the code even becomes too cumbersome. These are the only cases for the carefully considered use of public controls! Such a case does not exist for project 1, so preference should be given to project 2.
The 3rd project works with 3 sensor application windows. All three application windows are instances of the class FSensor, which is taken over from project 2. Therefore, only the source code of the class FMain is presented and commented:
[1] ' Gambas class file [2] [3] Private $iSensors As Integer = 1 [4] Private aSensors As New FSensor[] [5] Private aTrigger As Float[] = [0.1, 0.3, 0.5] [6] [7] Public Sub Form_Open() [8] Application.MainWindow = FMain [9] FMain.Center [10] FMain.Resizable = False [11] piboxOn.Picture = Picture["LED/led_green.svg"] [12] CreateSensors() [13] ValueBox1.Value = aTrigger[0] [14] ValueBox2.Value = aTrigger[1] [15] ValueBox3.Value = aTrigger[2] [16] End [17] [18] Private Sub CreateSensors() [19] Dim hSensor As FSensor, hObserver As Observer [20] Dim i As Integer [21] Dim aRanges As Float[][] = [[20, 21], [40.0, 42], [33, 35.8]] [22] [23] For i = 1 To aRanges.Count [24] hSensor = New FSensor(aRanges[i - 1][0], aRanges[i - 1][1]) [25] hSensor.Caption = "TEMPERATURE-SENSOR " & Str($iSensors) [26] hSensor.Tag = $iSensors ' The tag property stores the number of the sensor [27] hSensor.TriggerValue = aTrigger[i - 1] [28] hSensor.Show() [29] aSensors.Add(hSensor) [30] hObserver = New Observer(aSensors[i - 1]) As "Sensor" [31] hObserver.Tag = $iSensors ' The tag property stores the number of the observer [32] Inc $iSensors [33] Next [34] End [35] [36] Public Sub Sensor_Change() [37] Select Case Last.Tag [38] Case 1 [39] lblTemperature1.Text = Format(Last.Temperature, "##.0 °C") [40] Case 2 [41] lblTemperature2.Text = Format(Last.Temperature, "##.0 °C") [42] Case 3 [43] lblTemperature3.Text = Format(Last.Temperature, "##.0 °C") [44] End Select [45] End [46] [47] Public Sub Sensor_Close() [48] Select Case Last.Tag [49] Case 1 [50] lblTemperature1.Text = "--- °C" [51] Case 2 [52] lblTemperature2.Text = "--- °C" [53] Case 3 [54] lblTemperature3.Text = "--- °C" [55] End Select [56] End [57] [58] Public Sub ValueBox1_Change() [59] aSensors[0].TriggerValue = ValueBox1.Value [60] End [61] [62] Public Sub ValueBox2_Change() [63] aSensors[1].TriggerValue = ValueBox2.Value [64] End [65] [66] Public Sub ValueBox3_Change() [67] aSensors[2].TriggerValue = ValueBox3.Value [68] End
Comment:
Note: An alternative is to replace line 30 with this source code:
hObserver = New Observer(aSensors[i - 1]) As "Sensor" & Str($iSensors)
Now you get three observers, each with its own event name, and for this reason you can evaluate the Change() event and the Close() event separately if you replace lines 36 to 56 with the following two source code sections:
Public Sub Sensor1_Change() lblTemperature1.Text = Format(aSensors[0].Temperature, "##.0 °C") End Public Sub Sensor2_Change() lblTemperature2.Text = Format(aSensors[1].Temperature, "##.0 °C") End Public Sub Sensor3_Change() lblTemperature3.Text = Format(aSensors[2].Temperature, "##.0 °C") End
Public Sub Sensor1_Close() lblTemperature1.Text = "--- °C" ValueBox1.Enabled = False End Public Sub Sensor2_Close() lblTemperature2.Text = "--- °C" ValueBox2.Enabled = False End Public Sub Sensor3_Close() lblTemperature3.Text = "--- °C" ValueBox3.Enabled = False End