05-01-2012 02:48 PM
I have some questions about 2 related topics, the Xcontrol and the object-oriented programming.
The only thread I found here is a little bit old,
and even if it solved the problem there, I don’t think that the real question has been answered. (Worst, considering that it was an older version of Labview… I’m on Labview2011)
So, I’ll try to explain my situation first, hoping you’ll understand what I’m not sure of.
I want to develop a way to reuse some code in my companies… For different reason, some of us here have to build a custom UI, frequently, but each time by using the same sub-vi, or the same programming logic. (Like, an RS-232 serial communication, built with a custom control that contain all the possible command, or a graph with some custom control built-in…)
I did some C# and Java last years, and I really think that the object-oriented way is the perfect way to achieve this.
I rewrite the code, making it “by object”, and this way I am able to use my “object” in the User Interface Front Panel.
The common “problem” or what I’m still not sure is: “what is the best way to have the control of my class, on the parent UI…? I can’t decide which way is the best, and worst, I cannot understand what is the difference between an XControl (or a custom control) versus a LABVIEW CLASS. It is clear to me that this is pretty the same thing, and probably that the Xcontrol, was the older way to create some “object-oriented programming”… If so, just confirm it to me please…
In another hand, both of these approaches are great, but there still something “I don’t like…”
I still need to create some control reference (actually, a cluster reference) to pass some data that will be modified in a later time, for some other UI app, but I do not want to keep a library versioning, and change all the control of the older UI, just because we add a string in a sub-sub-vi.
Now, I find the Labview class pretty helpful, but I can’t understand why I still need to create and pass a control references, for each control in my object. In my head, the control of the object should appear automatically on the front panel. I wonder if I’m missing something here, cause, it would make sense that the “object” itself would be the control.
I can post an example if this is not clear.
If there is no “automatic” way to “get” the control UI, do someone could think about finding a way, to make control reference in a more fancy way, considering I’m using the LVOOP.
Thanks in advance,
Fakstory
Solved! Go to Solution.
05-01-2012 04:14 PM
XControls and LV Classes are not the same and XControls never were an alternative to Classes in LabVIEW.
A class I think you understand pretty well.
An XControl is a special UI element. You can create custom controls in LabVIEW that get saved as .ctl files. However, these are really just special groupings you create of controls that currently exist in LabVIEW with all their normal functionality. XControls not only allow you to group controls built into LabVIEW, but allow you to give them special functionality. The VIs that you write as part of the XControl run when and while an XControl is placed on a front panel.
Think about the increment and decrement buttons on a numeric control in LV. While they could be thought of just as boolean buttons, they have a special functionality whereby they change the value in the numeric indicator. This happens not only at run time, but also during editing. You don't actually see any of this functionality on the block diagram, you just see the data type. XControls allow you to do the same type of things.
The reason people often talk about LV Classes and XControls together is because, as I'm sure you've noticed, Class controls just look like cubes on the front panel. You will need to create an XControl that is a friend to the Class and then have the functionality of that XControl access the accessor methods of the Class in order to display or set the private data of the class.
05-02-2012 08:37 AM
Quick thought;
Coupling
Couling is one of the fundementatl esign patterns decribed the the Gang of Four and speaks to the relationship between Classes and the extent to which one class may be dependent on another class.
Pushing the GUI control refs down into a class makes that class dependent on the GUI. Thats OK if you will only have one GUI but that is not your stated goal but rather what you want to avoid.
Second thought
Not all of the classes used in an applciation are good candidates for re-use. In my LVOOP apps I find the higher level classes are app specific and can be dependent on the GUI since they serve no purpose without the GUI.
Suggestion
Implement a class that serves the GUI functionality at a minimum level that is common for most of your apps. Implement child classes with over-rides and additonal methods as required for the specific app you are developing today.
Ben
05-02-2012 10:19 AM
First of all, THANK YOU BOTH!
I was active on this forum 5 years ago and I’m glad to see that this community is still so powerful.
I thing I created a class that would be an Xcontrol. Never the less, this “control” is some kind part of the class because this makes no sense to me, to have 2 objects, 1 control, and 1 class… for the “same” functionality.
Never mind, I’ll probably choose what you said (both of you) because that makes sense, and because I am a little bit confuse about implementing a child classes with over-ride in labview…
@Ben, do you consider the idea of PackersFan, to be the solution? Or, could you point me some documentation/example that would enlighten me on the “child with over-rides”.
So, if I understand both of you correctly, I think that what I really want, it is some independents Xcontrols, with special behaviour, and if it’s possible, I want that special behaviour, be part of a class (and that the xcontrol have this class as child…), and that can be reuse by other.
This way, we separate the functionality from the control, but, it prevent me to have to link each controls on the GUI, with a reference in the class…
Correct me if I’m wrong, but I’m now thinking that my main app, would simply be the merging of 2 or 3 xcontrol, and this main application will only manage to pass the needed information between them…
Am I in the good direction?
Again, thanks in advance,
Fakstory
05-03-2012 08:45 AM
This type of design is best handled, as Ben said, by using an architecture which lends itself to decoupled modules and reuse. The most common of these is the model-view-controller architecture. In this architecture, your UI, control logic, and data collection are separate modules what communicate through well defined interfaces. For example, if you use a PCI-6521 DAQ board for analog acquisition, you really don't need to rewrite its control loop every time. Make it a module (a class). Better yet, make modules for the types of acquisition you will do (e.g. high speed analog acquisition), then create children for the actual hardware (eg. NI PCI-5124 or TEK DSO scope). You can do this for GUI elements as well, with the class containing a VI which will be run in a subpanel. Whether you go the VI in a subpanel or XControl route is up to you. XControls are easier for the end user to implement, but subpanels give you more flexibility and are easier to debug.
In short, you can certainly do what you would like to do, but you will probably need to learn some new architectures, as you have already determined. Check out the large applications area for lots of ideas. If you have specific questions, let us know.
05-03-2012 08:52 AM
I think the question about whether to use the inheritance structure being recommended or my suggestion about XControls as friends of the LabVIEW class is a little misled.
They are not exclusive options, but different aspects of your overall question.
You should absolutely use inheritance to create modules for your specific use cases.
Then we you get to worrying about the actual GUI (what will be on the front panel) that's when you will need to create XControls.
In short, use both, not one or the other.
05-03-2012 10:09 AM
I also struggled for a while with "where's the front panel of the class?" I am afraid I will have to be brief here, but I will tell you a little about an application I am writing. It might not directly answer your questions (which others have already addressed) but may give you some ideas.
The main application, i.e., the top-level vi, has no controls or indicators at all. The front panel is completely blank.
There are several modules which are classes, each with two data members - InputQueue and OutputQueue. The OutputQueue is the queue that the top-level VI listens on. Every module shares the same OutputQueue reference and has it's own InputQueue. The top-level VI can send messages to each of the modules InputQueue.
The GUI is one of these modules - a class with an InputQueue and OutputQueue. It has a method that is the user interface and therefore is set to show front panel when called by the top-level VI. (The top-level VI hides it's blank front panel when run)
This main user interface has two loops. The first is an event loop. Most of the event cases just send a message to OutputQueue which again is the same queue that all the other modules send their outputs to. The other loop dequeues messages from the GUI's InputQueue and sets indicators on the front panel. It is as simple as that.
What this means is that no modules can directly send anything to or get anything from any other module. They are clueless about the existance of anything other than themselves and the top-level VI.
As an example of how things flow, one ficticious module is a power supply. Someone changes the setting in the GUI and an event case sends a message to the OutputQueue. As far as the GUI is concerned it is done with that task. The top-level VI receives this and sends it to the power supply's InputQueue and possibly the DataLogger module's InputQueue.
The power supply module dequeues this and adjusts the power supply setting. At the same time the DataLogger writes this to a database. Periodically the power supply module gets a "SendStatus" message. It then reads the settings of the power supply and sends it to OutputQueue. The top-level VI dequeues this and sends the result to the GUI's InputQueue. The results are then written to indicators on the front panel of the GUI. Also the top-level VI sends the results to the DataLogger.
The GUI is not the only thing that can change the power supply setting. There is also a TestSequencer module which can send messages to the top-level VI. When it sends an adjust power message, the top level VI gets this and sends it to the PowerSupply and DataLogger module, and also sends a message to the GUI which updates the value of the control. Additionally when the top-level VI sends a start sequence message to the TestSequencer it also sends one to the GUI which will disable the power setting control.
As you can imagine there are many cases in the top-level VI's case structure. The message name is a string in the format "ModuleName:MessageName". The Case Select Tool from jcarmody (Jim Carmody) really helps manage things. Messages are objects using the LapDog Message Library written by daklu (Dave Snyder). The whole concept is described by Dave on Lava in Techniques For Componentizing Code.
05-04-2012 08:46 AM
Steve, your architecture is very similar to the actor framework, which was developed in cooperation between National Instruments and a LabVIEW contractor. Great minds think alike!
05-04-2012 09:09 AM
I wish I could take credit for it but the whole idea came from the thread on Lava "Techniques For Componentizing Code" by Dave Snyder that I linked to above. The Actor Framework existed when I started this but was not as mature as it is now. I remember looking at it and being amused by the two queues named "something something Thing1" and "something something Thing2".
In fact I recently updated one of the slave loop modules in the project which manages and controls an arbitrary number of devices on serial ports to use the Actor Framework. The devices are now actors but the interface to my main application is through one of these slave loops.
05-04-2012 11:20 AM
@Steve Chandler, I really appreciate the time you took to describe your application. In fact, this is a nice way to separate the GUI, from the module. Never the less, as you said,
(The other loop dequeues messages from the GUI's InputQueue and sets indicators on the front panel.) It looks like that you can only set indicator, and there is no way that those “indicator” can be used as a control! So, even if I like your solution, this side effect is the exact reason why I’m now thinking about Xcontrol.
In addition to that, all those implementations make sense to me, and I don’t really care about which way I’ll choose… The fact is that, I am often working with people that do not like Labview, or, they just have others “philosophy” in the manner of coding in Labview.
Knowing that, the object oriented programming would simplify that. It will offer a friendly way to “real” programmer (I mean, any C#, Java, or C/C++ Programmer…) to understand Labview code and it will force us to define a way, to manage our code…
So, even if I understand your way, I think that there is too many abstracted concept to be really useful in the long run here.
I want to use LV because this is so easy to create quick and powerful GUI. So, with Xcontrol, we keep “intact” the GUI, without forcing us to use Labview for the child class…
So, this is my last question, would it be “recommended” to link an xcontrol to a class, Class firstly created in labview, and may be, in the future, recoded in C#?
Thank you all,
Fakstory