01-13-2009 07:21 AM
For a program having multiple vis, can what the user sees as the main interface, the main front panel, actually be inside one of the subvis called by the real main program? That is, can we have a vi called Main that calls various vis as needed, including a vi called UserInterface? If UserInterface.vi is a subvi of Main, we would start this program by running Main. But Main vi would not open its front panel. Would UserInterface.vi have output terminals to carry control refs? But if UserInterface.vi keeps running for the life of the main application instance, it wouldn't pass anything out its terminals until everything ends. It could write refs into a global, though.
Can a subvi not have a front panel? A subvi that does not need to pass anything in or out on connector pane terminals, of course.
Or is wanting to do this completely off track? Maybe this completely violates some very basic principle?
Does the example "Simple Subpanel.vi" demonstrate part of the approach?
The reason for doing this would be that the user interface has lots of controls and a fair bit of logic that is devoted only to those controls, and the main vi also has lots of content, so it seems reasonable to partition them.
01-13-2009 07:36 AM
Hi Cebailey,
Personally I think it is the best way to use the main VI as the Front Panel VI, containing al the necessary controls and not too much functionality.
If you really want to have the Front Panel placed in a subVI, you might want to take a look at the following examples in the Example Finder:
Find Examples>>Building User Interfaces>>General>>
This link will also give you some more information regarding the use of a Subpanel control.
I hope this will help you with your program development!
Best regards,
Peter Schutte
01-13-2009 07:52 AM
>use the main VI as the Front Panel VI, containing al the necessary controls and not too much functionality
Maybe I should have FrontPanel.vi contain controls, and load all their refs into a cluster, and then call Main.vi and wire the refs cluster into it?
01-13-2009 08:20 AM
That is not what I meant.
Personally I think it is better (in most cases) to put all controls in the main.vi, so the main.vi will become the front panel VI.
To keep a good overview in the block diagram of your main.vi, you can put some of the programming code (or a lot in some cases) in different SubVI's.
Best regards,
Peter S
01-13-2009 08:58 AM - edited 01-13-2009 09:00 AM
01-14-2009 07:29 AM
Your basic idea is very sound, has a lot of advantages and flexibility, and I have shipped code which used it. LabVIEW has a quirk that adds an issue, however. If you are running a built application, normally the application will exit if there is not an open front panel. For this sort of architecture, it means you always need an open front panel. There are several ways to approach it:
There are probably a lot of variants to this theme, but that is the general idea. Even though it is more complex, I like option 3 because it allows me to reuse the splash screen as an about box.
Use queues to communicate between your GUI and main VI. I usually use two, GUI->Main and Main->GUI. If you think of the system as a producer/consumer system with the producer and consumer in different VIs, the architecture becomes more obvious. Use single-element queues or action engines as your "globals" to avoid race conditions.
Good luck. Let us know if you need more help.
01-14-2009 08:26 AM
DFGray, thank you, I understand most of what you wrote and it sounds like all three of your approaches would do what I was roughly thinking about very nicely. I think your "1) GUI first then launch main" is almost what I am already doing, if I change the way I think about what is the main program. After all, a heirarchical view of the whole program is going to put the GUI at the top. Which is fine - what does LV care which vi I want to think of as the "main" one?
But I am curious why I want to use queues between GUI and Main. I already use queues for producer consumer patterns frequently, and have a good feel for them. But why here? I thought of the GUI as a pretty dumb vi that bundles a bunch of control refs for reading and writing and sometimes color change or other property node use by everybody else. What's preferable about the queue approach?
One thing I have not thought through thoroughly is my use of mouse and keyboard events, often with dynamic registration so I can "turn off" the event handler when moving to other parts of my program where they are irrelevant. I've done this in the current main vi whose front panel is the user interface, and I've done it in subvis nested down inside of the main/UI vi. It should work the same way if I have to pass control refs from a vi which is only the UI, right? I have my dynamic event use giving me what I want now, but I've only had a little experience with them.
01-14-2009 09:08 AM
One other disadvantage of the approach you're proposing is that subVIs can only execute at the same or higher priority as the VI that calls them. Typically you would let your GUI run at low priority and your data processing at a high priority. If all your logic is in your main VI running at high priority and your GUI is called as a subVI, the GUI will also execute at high priority, taking time away from your processing.
Also, a cluster of control references stored in a global variable is an ugly way to handle GUI updates. It's very easy to update data within your program and forget to update the control reference, or vice versa. I used to work on code written this way and it was a constant problem because someone would make a change to the logic without unbundling the control reference, and then the front panel would not show what the code was actually doing. A year later you decide to modify the GUI, deleting several elements, and suddenly all your control logic has to modified to deal with the control references that no longer exist. Eventually you'll get tempted to cheat and read front panel control values directly off the references, and then you've lost dataflow entirely and it becomes a mess. A better approach, as DFGray suggested, is to pass your data to the GUI (using a queue) and put the display logic inside the GUI, keeping it separate from the rest of your code.
01-14-2009 09:52 AM
The example you mentioned is a good place to start, but remember that there are multiple ways of getting a VI reference to put into your subpanel. You can dynamically link to the plugin VI using VI server - in which case the Main VI is calling the plugin. In this situation, the main vi will appear in the plugin's call chain and it will be executing with the same priority as the Main VI.
However, you can also use VI server to launch the plugin as a separately executing VI that has its front panel "Hidden". In this situation, the plugin will be executing as a top-level VI and so doesn't know that it is a plugin because the Main VI isn't technically calling it.
Mike...
01-14-2009 10:02 AM
Wow. Wow. This is straining my understanding, I can just barely follow some of it.
The execution priority is an interesting point I didn't think of, but can imagine how to investigate.
I appreciate the reasoning behind using a queue. But I don't quite picture it yet - what are the queue elements? Maybe a cluster that contains the data value to be passed and a reference that identifies what control it is coming from (in Ui>Main) or going to (in Main>Ui)? Or am I just going back to the disadvantages of reference objects with that idea? There has to be some mechanism that points at a control, right?
Thanks for the links that took me to Action Engine / Functional Global explanations. I had heard of Functional Globals but didn't know what they contained. Having a Get method and Set method specified by an enum driving a case structure with a shift register in it makes perfect sense. This vi has to be made reentrant, right?
This is a lot of new stuff.