Hi all. I’m an absolute beginner with Xojo and come from a non-object orientated background. I’m writing a Linux app that controls a small robot. I’ve got some serial ports up and running and the UI updating. I’m using global variables for some of the info that is needed in different parts of the code (for instance, motor speeds being held in a global). I know, I know… globals are bad.
To make globals, I created a Module at the App layer, renamed it to Globals and then started adding properties in there for the various things I needed. So far so good, some integers, some strings, etc… Everything was working.
Once I got my test code going, I came back to clean things up a bit. In C, I would create a struct and then group some commons things together. Looks like I could do that with Structure in Xojo, but the recommendations was to create a Class instead. So I created a class at the App level, added a few properties to it, created a Property in my Global module pointing to the Class and then went to use that new variable in my code, and run into a nil error. So, classes are being dealt with differently then the built-in types I guess. Where am I going wrong?
Steps to reproduce:
- Create new desktop Project
- Insert → Class
- Rename it as ClassTest, and then add two properties (right click ClassTest on left hand bar, insert property). Rename property 1 as ‘prop1’, type integer, default value = 0. Rename property 2 as ‘prop2’, type integer, default value = 1.
- Left click, then Insert from the menu bar and Module. Rename as Global.
- Right Click Global module, add property. Rename to Test1 and type as ClassTest
- Right Click Global module, add property. Rename to Test2 and type as Integer
- Right Click ‘Window1’ and add event handler for ‘opening’
- In Opening, add the code :
- Test2 = 2
- Test1.prop1 = 2
- Run the code. It will fail with a NilObjectException on the test1.prop1=2 line.
So… I need to initialize my custom Class variable somewhere?
Classes require an instance, where intrinsic types do not. Some built in types are classes that you do need to create an instance of (like Clipboard if you’re looking for an example).
To create an instance of your class, use the new
keyword.
var oThing as new MyClass
or
var oThing as MyClass
oThing = new MyClass
Yup, exactly! Anywhere before you use it will suffice. If you’ve got an instance on the Window1, then Window1.Opening is a good place.
Here’s some documentation to help: New — Xojo documentation
Thanks Tim. If I add a ‘var Test1 as new ClassTest’ to my Window1 Opening, the code within Opening works great. How do I refer to that variable in other functions/events though?
For instance, if I add a button to Window1 and attached ‘Pressed’ event to it and then try to refer to the Test1.prop1 variable it either gives me a nil error (if I still have the Test1 class defined in my Global properties) or that The Test2 item doesn’t exist. If I add ‘Var Test1 as New ClassTest’ in the button pressed event, it just creates a new local variable there.
I know this is a pretty basic question with an answer that is obvious once I get a little more experience. Thanks!
var
is a variable local to the method that you implement it in, so at the end of that method it is no longer accessible. A property is how you would store something beyond that.
For a property of Window, it remains until the Window is closed. A globally scoped property on a module is always in scope and will remain unless you clear it yourself with myModule.myClassProperty = nil
. There’s some more information about scope in the documentation here: Properties — Xojo documentation
I recommend using protected-scoped properties to enforce the namespacing (requiring the code read myModule.myClassProperty
instead of allowing myClassProperty
).
So create a property in a place where the scope is as tight as it can be while still being useful for your project. Then, in the nearest available Opening event (a global you will likely want in App.Opening, a Window property in the Opening event of that window), create an instance to store in the property.
Your end result should look something like this (for a Window scoped example):
Edit: Fixed code sample in screenshot
1 Like
Perfect! The me.xxxxx bit was the part I was missing. Thanks!
Putting all my globals into the window scope will work nicely in my app. Thanks for leading me down the path.
Glad to have helped! You can mark the thread so that others can tell it’s been solved from the topic list. Click the button that says “
Solution” under the post that best answers your question.
1 Like