At the very end of my last post I suggested that perhaps the best way to display user data on your application’s GUI is to avoid sending data to the GUI in the first place. Of course the big question is how the GUI can display data that you don’t send to it?
The programmatic slight of hand that explains this paradox is a feature of LabVIEW called a subpanel. To understand how subpanels fit into the overall LabVIEW “ecosystem”, let’s review for a moment. As anyone who has used LabVIEW for more than 5 minutes will recall, every VI you create has 3 main parts:
- The Front Panel — This part provides the VI with a user interface for interacting with the routine.
- The Block Diagram — This window is where you put the graphical source code that describes what you are trying to do.
- The Connector Pane/Icon — This part allows you to call your VI from the block diagram of another VI.
Now all programming environments have places to enter source code and methods for calling or reusing other code, but the Front Panel is really unique to LabVIEW. With most languages, you have to write code to create the GUI, but with LabVIEW, the GUI is part of the code. Just as calling one VI from the block diagram of another VI is a way to modularize your program’s logic, so subpanels provide a way to modularize your program’s user interface by incorporating the front panel of one VI into the front panel of another VI.
But Why Subpanels?
To be honest, there are other techniques for “modularizing” user interfaces within LabVIEW, and we’ll take a quick look at a couple — though to be honest we should call the result of one technique “pseudo modularity” because while the interface looks modular, it’s really not.
First we want to consider XControls. A couple years ago at NIWeek, I presented a session on how to use XControls, so it’s a topic with which I am familiar. XControls approach the question of GUI modularization by providing a mechanism for creating custom front panels controls that implement custom functionality not found in standard controls. Although they are very powerful, they have some issues:
- Complexity: XControls are difficult to create and require both greater skill on the part of the developer and advanced knowledge of how LabVIEW works internally. As you can imagine, an XControl of even modest complexity can take a long time to develop. The result is that the functionality they encapsulate must be sufficiently reusable to justify the effort required to create the XControl.
- Can Complicate Debugging: One of the “interesting” aspects of using an XControl is that they are almost always running. Of course, when you think about it, this makes sense. A control obviously has to exhibit some useful behavior at run time. However, during development they must also be able respond to changes that the developer is making. For an XControl this requirement means that, on some level, it is running as soon as you drop it down on a front panel. While this fact obviously complicates the process of debugging the XControl itself, it can also adversely effect the debugging of the program you are trying to create — especially if the XControl uses some of the same libraries that you use in creating your program. You can see limited access to subVIs because they are being called in the XControl and so are already running, or are at least reserved for execution.
- Support is Limited: Actually, “stinks on ice” is probably closer to the truth. Documentation is poor, examples are practically nonexistent, and because NI considers it an advanced topic, tech support is often no real help.
Problems with XControls
Tab Controls — Just Say “No”
This technique is the one I described as “pseudo modularity”. As a control metaphor, the tab is familiar to anyone who has been around computers for a while. However, operating system designers have been moving away from tab interfaces for a variety of reasons. To be fair, I would like to start this section with some of the positive things about tab controls, but to tell the truth I can’t think of any…
- Complexity: While a tab control might help visually organize the 30 or 40 controls and indicators on your front panel, the block diagram can rapidly become a mess as you try to deal with the functionality associated that many terminals. Moreover, because the tabs hide complexity, they increase the likely that your front panel will have 30 to 40 controls and indicators.
No Reusability: Let’s say you create really nice a user interface on one tab of your application. Now let’s further postulate that the interface is so good that another internal customer wants you to build them an application that uses the same interface. How do you do it? Well, with tabs, your option is to cut and paste the controls and then rebuild the logic on the block diagram.
Of course that’s just the beginning of the challenges. You still have to verify that the code works the same in the new context, and you have to hope that the new program’s timing doesn’t effect how the interface works.
- Compatibility Problems: It is unfortunately not uncommon to see posts on the forum where someone is wanting to know why common controls and indicators don’t work as expected when they are on tab controls. Such questions are not uncommon because, to be perfectly frank, LabVIEW has a long history of tab controls causing a variety of screen update and performance problems.
Confused VI Server Interface: Normally when working with controls and indicators the terminals of which are on your block diagram, finding there references programmatically is easy. With a reference to the VI’s front panel you can get an array of the controls on the front panel, and the reference to the control will be in that array.
But a tab control complicates the whole process. First you get a reference to the tab control, from that you get an array of references to the pages in the tab control, and once you have found the right page you can get the array of control references containing the control reference you want.
Problems with Tab Controls
A Good Solution for GUI Modularity
But there’s another way to answer the question: “But Why Subpanels?”: the advantages that subpanels offer. But please note that you can only expect to realize these advantages if you use subpanels properly — which is to say, VIs appearing in the subpanels are autonomous processes that encapsulate the logic for a single operation and, when necessary, display the results of those operation on their own front panels.
- Subpanels Simplify Code, Reduce Memory Footprint and Improve Efficiency: When using subpanels you are able to realize these benefits because the minimal code required implement them is almost always smaller than the code you take out that implemented the redundant communication and display formatting operations. In addition, remember that because you are reducing the data manipulation the code is performing, you are also reducing the memory (and CPU) needed to manage it.
- Subpanels Make Code Robust: When designing a process VI that will run in a subpanel, it is easier to create highly cohesive code with very low coupling between it and the remainder of the application.
Subpanels Generalize GUI Structure: Working with subpanels inherently puts you into a mode where you start thinking about the GUI at a higher level. One side-effect of thinking in this way is that so much application-specific logic is moved into subpanels that, in the end, the GUI itself doesn’t know or care what application it is running.
This point is particularly interesting because the interface could get so generic that it could be divided up into separate dedicated areas like this:
Normally the subpanel frames would not be visible, and there would be no annotations in each section, but then the front panel would be basically blank, and very uninteresting to look at. To get an idea of what could go in each section, consider these descriptions. Remember, not all of these sections would necessarily be on every screen, and their sizes can be adjusted to fit requirements.
Header: The intent of the header subpanel is to show VIs that present information that is unlikely to change as a function of the screen being shown in the body. This area could include things like the current time, the operator who is logged in, total operating hours or the name of the display.
Footer: This subpanel extends across the entire bottom of the screen. It could hold VIs that provide things like a status display, or a scrolling alarm status list. Like the header, this section ideally wouldn’t change during the course of program execution.
Body: The application’s main display VIs would go in this subpanel.
Sidebar: The VIs providing this section’s contents of could include things like navigation buttons, or supplemental information that is related to the main display.
If you have ever done any web development, this basic layout might look a little familiar, which is appropriate since I “appropriated” the idea. One of the key concepts of the web is to separate content from where and how the content is displayed to the user. This approach in LabVIEW is a (small) step in that direction with the subpanels providing the display structure.
So combine these advantages these with a host of others, and you can begin to get a feel for why I consider subpanels to be among the top 5 features added to LabVIEW — ever.
Let’s See Them Work!
To get our first taste of subpanels in action, we won’t go to the extent of creating a fully abstracted interface like we just saw. Rather, I will show how to manage one subpanel — and you can expand it from there, however this post is already getting long, so we’ll have to wait until next time to look at that code.
Until next time…