I have a problem when I drop a class on my window (which I would like because I have event definitions) which is really annoying. What I do:
-Create a class and set one or two values in the constructor
-Drag it to window1.
-Calling a method of this class and display the value(s).
First the values are shown correctly. Then I program a little bit more and suddenly the values aren’t set anymore (but constructor is called!). To solve this I just delete the class on my window1 and drag the class again into the window1 and my problem is solved.
if you open project in Arbed, you can see the control instance here.
And there your values are stored.
So xojo calls constructor, you set values and than Xojo loads into object the initial values defined in control instance on window.
[quote=119311:@Urs Jäggi]I have a problem when I drop a class on my window (which I would like because I have event definitions) which is really annoying. What I do:
-Create a class and set one or two values in the constructor
-Drag it to window1.
-Calling a method of this class and display the value(s).
First the values are shown correctly. Then I program a little bit more and suddenly the values aren’t set anymore (but constructor is called!). To solve this I just delete the class on my window1 and drag the class again into the window1 and my problem is solved.
Xojo behaves weirdly with the preallocated values. It’s something like this:
People expect, as other environments, is does initializations like the following:
[code]Class._init() //<-- allocate things, set initial values, etc. Raise Constructor(), open()…
Event Class.Constructor()
Event Class.Open()
//-- Object life
Event Class.Close()
Event Class.Destructor()
Class._release() // Internal clean up
And Xojo does anything like this (I do consider it an irritating bug, some say it’s a “characteristic”):
Class._init() //<-- allocate things, etc. Raise Constructor(), open(), _init_values()… !!! Wow!!! What?
Event Class.Constructor()
Event Class.Open()
Event _init_values() // !!! What? this hidden “event” destroyed my settings in the constructor?
// Have I made wrong calculations in the open() without my predefined values?
//-- Object life
Event Class.Close()
Event Class.Destructor()
Class._release() // Internal clean up
Class MyClass
Property Public n1 As integer = 123
Property Public n2 As integer = 0
Sub Constructor()
n2 = n1 * 2
End Sub
End Class
Dim c As New MyClass // c.n2 = 246
What Xojo does (something like):
Class MyClass
//Property Public n1 As integer = 123
//Property Public n2 As integer = 0
Property Public n1 As integer = 0
Property Public n2 As integer = 0
Sub Constructor()
n2 = n1 * 2 // ------ 0 * 2 = 0
End Sub
Sub _init_values() // Called after Constructor, after Open() it it have one, not sure,
// don't remember the fail exactly
n1 = 123
End Sub
End Class
Dim c As New MyClass // c.n2 = 0, and n1 was 0 too at constructor() time.
This is only somehow true for windows, controls and class instances added to a window via the IDE. It doesn’t happen with class instances created in code.
But then why would somebody want to set the initial value twice - or even three times as in the OP - on an class instance added to a window via the IDE? Just set it in the IDE, or use the window’s Open event (which is guaranteed to be the last on window startup).
Property Public n1 As integer = 123
Property Public n2 As integer = 0
Sub Constructor()
n2 = n1 * 2
End Sub
End Class
Dim c As New MyClass // c.n2 = 246[/quote]
Works perfectly. Both when the class is added and instantiated in code in a window or dragged onto the window in the navigator.
What about use the value? Maybe talking this way the concept can be better understandable. I’ll define a property called PI and set it’s value to 3.14 in the constructor If I use it I wish to use it as 3.14, not zero? Is it hard to understand?
In any other language of this world preinitialized values comes with it’s values predefined. Interestingly even Xojo! Sometimes…
The problem is this “Sometimes”. Should be Ever! The name of this is consistence of behavior.
It is consistent if you think about how Xojo works!
When you drag a class (or control) onto a window an instance of that class is created. If you later change something in the class, which is not compilable source code, it will not be reflected in this specific instance.
Putting a value into the “Default” text field of a property definition is read only once by the IDE (when dragging the class onto the window thereby creating the instance), not on compile time.
For example if you later change the “Default” value in the text field of a property definition. This change will not be reflected in all existing instances, only on instances which one creates later.
This kind of behavior can introduce bugs if you forget to change those old values to the new ones, but it’s really not the heart of the question here. The real problem is where in time those values are set. They must be pre-constructor. Init time. Not post-constructor. We must receive the preset values in the user space since t0. We can’t start use the preset values and a exotic xojo intrusion comes from nowhere and change the property values.
When you write your “default” value in Xojo, they are written as:
Dim p As Type = Value
Not:
Dim p As Type = Nil
SetEvent_SetValueAfterOpen(self, p, Value)
Again: a default value entered in the IDE in the property definition text field Dim p As Type = Value
… is applied at creation of the instance - when the class (or control) is dragged onto the window.
You should see a window instance in the IDE as a live object (like XIBs in Xcode), not as a piece of source code (like in Visual Studio). Then it makes perfect sense.
A live object is an instance, which can, and is, converted to source code (Like Delphi does). It have native support in the language for that. For example, here is a Sub-class of a Form (Window) with all the designs and components and it’s initial values.
type
TForm1 = class(TForm) //< Define the class, the implementation of the procedure will be elsewhere after.
// Not included here.
db1: TSL_Database;
table1: TSL_Table;
OpenDialog1: TOpenDialog;
Panel1: TPanel;
tvBrowse: TTreeView;
Panel2: TPanel;
Splitter1: TSplitter;
Panel3: TPanel;
sg1: TBestStringGrid;
Panel4: TPanel;
sql2: TSL_Table;
table2: TSL_Table;
Panel5: TPanel;
Panel6: TPanel;
edSQL: TComboBox;
MemoTime: TMemo;
Splitter2: TSplitter;
bnOpenDB: TButton;
bnEditTable: TButton;
bnExecSQL: TButton;
MainMenu1: TMainMenu;
Database1: TMenuItem;
able1: TMenuItem;
Info1: TMenuItem;
Libraryversion1: TMenuItem;
Libraryencoding1: TMenuItem;
Open1: TMenuItem;
Edit1: TMenuItem;
Close1: TMenuItem;
procedure table1Data(Sender: TObject);
procedure bnExecSQLClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure sql2Data(Sender: TObject);
procedure bnOpenDBClick(Sender: TObject);
procedure tvBrowseChange(Sender: TObject; Node: TTreeNode);
procedure editSelectedTable(Sender: TObject);
procedure Panel6Resize(Sender: TObject);
procedure Libraryversion1Click(Sender: TObject);
procedure Libraryencoding1Click(Sender: TObject);
procedure Close1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
tableNode : TTreeNode;
viewNode : TTreeNode;
indexNode : TTreeNode;
dbNode : TTreeNode;
procedure processRow(row:TSL_Row;r:integer);
procedure drawCaptions(row:TSL_Row);
end;
var
Form1: TForm1; // < Here is the variable. The reference holder of this class.
//======
object Form1: TForm1 // < Here is the instance declaration. The preset initial values.
// This instance exists since t0 with those numbers.
Left = 237 // It includes ALL the values, including of sub-compoments of this class
Top = 242
AutoScroll = False
Caption = 'SQLite Browser'
ClientHeight = 638
ClientWidth = 898
Color = clBtnFace
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Arial'
Font.Style = []
Menu = MainMenu1
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 15
object Splitter1: TSplitter
Left = 249
Top = 0
Height = 638
end
object Panel1: TPanel
Left = 0
Top = 0
Width = 249
Height = 638
Align = alLeft
Caption = 'Panel1'
TabOrder = 0
object tvBrowse: TTreeView
Left = 1
Top = 34
Width = 247
Height = 603
Align = alClient
Indent = 19
TabOrder = 0
OnChange = tvBrowseChange
OnDblClick = editSelectedTable
end
object Panel2: TPanel
Left = 1
Top = 1
Width = 247
Height = 33
Align = alTop
TabOrder = 1
object bnOpenDB: TButton
Left = 4
Top = 5
Width = 75
Height = 25
Caption = 'Open DB'
TabOrder = 0
OnClick = bnOpenDBClick
end
object bnEditTable: TButton
Left = 82
Top = 5
Width = 75
Height = 25
Caption = 'Edit Table'
TabOrder = 1
OnClick = editSelectedTable
end
end
end
object Panel3: TPanel
Left = 252
Top = 0
Width = 646
Height = 638
Align = alClient
Caption = 'Panel3'
TabOrder = 1
object Splitter2: TSplitter
Left = 1
Top = 545
Width = 644
Height = 3
Cursor = crVSplit
Align = alBottom
end
object sg1: TBestStringGrid
Left = 1
Top = 35
Width = 644
Height = 510
Align = alClient
ColCount = 2
DefaultRowHeight = 18
DefaultDrawing = False
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Arial'
Font.Style = []
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goColSizing, goThumbTracking]
ParentFont = False
TabOrder = 0
OrderIcon = False
OwnerDrawText = False
ColWidths = (
12
64)
end
object Panel4: TPanel
Left = 1
Top = 1
Width = 644
Height = 34
Align = alTop
TabOrder = 1
object Panel5: TPanel
Left = 530
Top = 1
Width = 113
Height = 32
Align = alRight
BevelOuter = bvNone
TabOrder = 0
object bnExecSQL: TButton
Left = 16
Top = 3
Width = 94
Height = 26
Caption = 'Exec SQL'
TabOrder = 0
OnClick = bnExecSQLClick
end
end
object Panel6: TPanel
Left = 1
Top = 1
Width = 529
Height = 32
Align = alClient
BevelOuter = bvNone
TabOrder = 1
OnResize = Panel6Resize
object edSQL: TComboBox
Left = 5
Top = 5
Width = 431
Height = 23
ItemHeight = 15
TabOrder = 0
Text = 'select * from sqlite_master;'
end
end
end
object MemoTime: TMemo
Left = 1
Top = 548
Width = 644
Height = 89
Align = alBottom
TabOrder = 2
end
end
object db1: TSL_Database
Left = 40
Top = 320
end
object table1: TSL_Table
Database = db1
SQL = 'select _ROWID_,* from songs limit 1000;'
OnData = table1Data
Left = 40
Top = 376
end
object OpenDialog1: TOpenDialog
Left = 48
Top = 136
end
object sql2: TSL_Table
Database = db1
SQL = 'select ROWID,* from sqlite_master;'
OnData = sql2Data
Left = 40
Top = 432
end
object table2: TSL_Table
Database = db1
Left = 40
Top = 264
end
object MainMenu1: TMainMenu
Left = 396
Top = 56
object Database1: TMenuItem
Caption = 'File'
object Open1: TMenuItem
Caption = 'Open Database'
OnClick = bnOpenDBClick
end
object Close1: TMenuItem
Caption = 'Close'
OnClick = Close1Click
end
end
object able1: TMenuItem
Caption = 'Table'
object Edit1: TMenuItem
Caption = 'Edit'
OnClick = editSelectedTable
end
end
object Info1: TMenuItem
Caption = 'Info'
object Libraryversion1: TMenuItem
Caption = 'Library version'
OnClick = Libraryversion1Click
end
object Libraryencoding1: TMenuItem
Caption = 'Library encoding'
OnClick = Libraryencoding1Click
end
end
end
end