Jump to content
hooovahh

Multi Panel Interface

Recommended Posts

Cool, thanks for posting this! It reminds me a little of the panel handling in ALOHA. I'm in the (background) process of writing an AF child that encapsulates all the panel handling (and announces data streams).

Share this post


Link to post
Share on other sites

I've never heard of ALOHA but might check it out.  If it is an unbounded number of panels I assume they are doing similar techniques with Parent Child relationships.  Using subpanels alone does work but you have a limited number because you cannot add a subpanels (or any other control) at runtime.

Share this post


Link to post
Share on other sites
Is using the win32 'child window' declaration a hard and fast requirement? 

Well...do you have another mechanism for attaching floating windows to other windows?  If you go with subpanels you can do it but you need something like 100 subpanel controls, all hidden on start, and then when you need to insert a VI you go get one and move it to the location you want and insert a VI.  But if you need 101 controls then you need to go and make more subpanels in the source and make a new build.

 

If subpanels could be added programatically at runtime this would be fine but you can't so I don't know another way to do this.

 

By the way, I have tested this UI design with subpanels and it does work, but it is more limited.

 

EDIT: Also things like panel resize while docked gets a little tricky with subpanels, where the user32.dll gives access to allow a window to be resized like a floating window.

Edited by hooovahh

Share this post


Link to post
Share on other sites
If subpanels could be added programatically at runtime this would be fine but you can't so I don't know another way to do this.

 

Your code already has this problem with tabs - what if someone wants more than 20 pages?  But since Tab Controls are Enums, I don't think there'll ever be the facility to add pages at run-time.

Share this post


Link to post
Share on other sites
Your code already has this problem with tabs - what if someone wants more than 20 pages?  But since Tab Controls are Enums, I don't think there'll ever be the facility to add pages at run-time.

 

If you use the OS tab control via activex or .NET. you can add/remove pages dynamically.

Share this post


Link to post
Share on other sites
Your code already has this problem with tabs - what if someone wants more than 20 pages?  But since Tab Controls are Enums, I don't think there'll ever be the facility to add pages at run-time.

I totally knew that going into it.  But I feel like having 500 tabs and have them be hidden is not a big issue, but having 20 subpanels for each tab making 10,000 subpanel controls just not being used, would be overhead that may have an effect on performance.  What I'm saying is the 20 page limit is arbitrary sure, but can be a very large number without any real issue.

 

If you use the OS tab control via activex or .NET. you can add/remove pages dynamically.

I never thought about this.  It sounds like it might be a good idea to try since adding/removing pages dynamically would be a nice feature that the native tab can't support.

 

EDIT: or VIBox might work too.

Edited by hooovahh

Share this post


Link to post
Share on other sites

Had a chance to look more closely now.

 

You can save yourself having to load "special" VIs that take a custom event via controls or detecting mouse over/move events on the child FP (checking mouse coordinates in region etc in the main VI) by attaching a callback to the VI when you load it. The callback can be attached to any VI to piggy-back the child VIs events and inject your own user event that you can access in your main VI. You can attach these call backs to not only the VI server events (close, mousemove, resize et. al.), but controls/indicators as well. I think it would greatly simplify you main VI.

 

mdiCB.png

 

mdi.png

 

mdiExample.png

Edited by ShaunR

Share this post


Link to post
Share on other sites
Had a chance to look more closely now.

 

You can save yourself having to load "special" VIs that take a custom event via controls or detecting mouse over/move events on the child FP (checking mouse coordinates in region etc in the main VI) by attaching a callback to the VI when you load it. The callback can be attached to any VI to piggy-back the child VIs events and inject your own user event that you can access in your main VI. You can attach these call backs to not only the VI server events (close, mousemove, resize et. al.), but controls/indicators as well. I think it would greatly simplify you main VI.

I don't fully understand what you are saying but am curious.  I have used event call backs on .net DLL calls so I am passingly familiar with them but I don't know how they could help simplify my code.

 

So when the mouse enters my panel VI I can have that run a VI through the callback feature, which can generate a user event, that tells the parent this event has happened?  I don't see how that is better then at the moment where the VI ref can be passed to the parent, then register for the mouse enter event, causing the event to be handled in the parent when the mouse enters the panel.

 

Don't take this post as me saying "This is stupid and my way is better" I just don't fully understand how it can help because I've had very little experience with event callbacks.

Share this post


Link to post
Share on other sites
I don't fully understand what you are saying but am curious.  I have used event call backs on .net DLL calls so I am passingly familiar with them but I don't know how they could help simplify my code.

 

So when the mouse enters my panel VI I can have that run a VI through the callback feature, which can generate a user event, that tells the parent this event has happened?  I don't see how that is better then at the moment where the VI ref can be passed to the parent, then register for the mouse enter event, causing the event to be handled in the parent when the mouse enters the panel.

 

Don't take this post as me saying "This is stupid and my way is better" I just don't fully understand how it can help because I've had very little experience with event callbacks.

 

It does run the VI, but the VI is attached, externally, (for want of a better explanation), so you do not need any code whatsoever in the child to get it's events and the top level VI doesn't co-opt the childs events (the child can behave as as a discrete module-handle its own events and broadcast them when actioned to the parent).

 

I'm also not saying it is better. It's just a technique I have found that keeps responsibilities modularised and the parent clean of module specific event handling.

Share this post


Link to post
Share on other sites
It's just a technique I have found that keeps responsibilities modularised and the parent clean of module specific event handling.

I am all for this type of development, and I think I can see how this could help with that.  Thanks.

Share this post


Link to post
Share on other sites

Hi,

 

      I had a question related to Load and save settings in your program. I just wanted to know how would you implement save and load front panel vi's? also, if you load Front panel settings, how would you place all the vi's exactly on the same location when saved? 

Share this post


Link to post
Share on other sites

I had a function a while ago and I'm not sure if it was included in this post but it would give relative position from a parent to a child, or absolute position from the desktop to the child.  Saving this information, then using the Windows Move function on load could be done relatively easily.  

 

Now if you have custom connections for a child window you'll need some custom way of re-making those connections on load.  This demo just shows a random number generator for a window, but one could see that a publisher subscriber architecture could be used where a child window subscribes to data to display.  And these are the connections I am talking about that would need to be saved and loaded as well. 

Share this post


Link to post
Share on other sites

Hi,

 

      I had question regarding the custom connections. For eg: User event for custom loading is created, similar to quit event. Next step, try to load Custom UI, but it applies to all Child vi's on User interface like Quit event, in this case how to make connection to load only particular child vi.

Share this post


Link to post
Share on other sites

Okay so this is all conceptual and I haven't actually tested any of this.  Notice that in the Run Panel case in the Main.vi you are creating a variant to give to the child.  This variant is actually similar to a Variant Repository I posted earlier but that is a different story.  In this Variant we embed the same Quit user event.  We also embed a Set Settings event, a Get Settings event, and a Get Settings Reply event which is unique for each child.  The idea is that you could keep this information and can send user events to one child at a time, or throw it in a loop and set all of them.

Share this post


Link to post
Share on other sites

Hi,

 

       Thanks a lot for the reply.  I want to be more specific, In the main vi there is a case called quit Vi , In that i actually replaced quit and made it set settings and removed for loop.In the child VI (Numeric graph), there is a case set settings i created a erase history. I used a runtime menu for set settings. I loaded 2 or 3 child vi's on FP and tried what u mentioned above, but all the vi's Graph history was erased. So could please give me a solution of how to make unique for each child? if any example pls do post.

Edited by Jay0909

Share this post


Link to post
Share on other sites

No I have no examples.  This was just test proof of concept code and I have yet to use it in an application.  I don't fully understand what you are trying to do.  In the example there is the global event (or rather an event for all children) which is Quit, and then there are events for each child like Set Settings as mentioned earlier.  

 

You can generate this Set Settings event which has a variant as the data, and depending on the value of the data do different things.  Like the data of the variant can be a cluster of a String, and a variant.  The String can be the type of setting you are attempting to set, and the variant can be the payload of the event.  I personally use Variant attributes but that is harder to explain if you are unfamiliar with them.  Post some code if you are still confused.

Share this post


Link to post
Share on other sites

Hi,

I had a question, for eg: if i have 50 child vi's on FP, and if i generate a user event from main Vi, which child vi will respond first? When i generate user event in Main vi, how does actual reach to all child vi, I mean to say one by one or simultaneous? And also

In the above example if 50 child gets event at the same time. How do v actually recognise all 50 response from child vi's? So, what's the method to get response one by one from all child vi's ?

Share this post


Link to post
Share on other sites

Well the idea is to use a publisher subscriber design.  So this means you can communicate 1 to 1, or 1 to N from the parent, but only 1 to 1 from the child.  So you could send out a single global event that all children get.  This would then be acted on at more or less the same time on all children at once.  Just like how you send the Quit and they all quit at once, no child is waiting for another child to quit.

 

As for the response.  Because the design is 1 to 1 from the child perspective, I'd say you could send out a global out, from the parent, then each child can generate the same event back to the parent, with different data identifying which child it came from.  Looking at my code I feel bad for not completing this part which was in my head but not in my code.  Notice that again there are 3 events made which is unique for each child.  Set Settings, Get Settings, and then Get Settings.Reply.  The intent was the parent could send 1 to 1 using Set Settings.  And the parent could get data by sending a 1 to 1 on Get Settings, which would cause the child to send back data on Get Settings.Reply which the parent would register for.  I also can't believe how many subVIs don't have icons, such a shame.

Share this post


Link to post
Share on other sites

Hi,

 

         In this topic you have discussed about, reading analog, digital Inputs etc. from a hardware using actor framework. I'm really interested in learning this concept, Could you please tell me in Detail how could you achieve in reading analog or digital signals and passing on to child vi's using user events. 

Share this post


Link to post
Share on other sites

Again I'd like to stress that this has never been done with this design pattern but could be done, and could be done a multitude of ways.  

 

Let yoru DAQ actors start up, and then have it publish to a functional global (or something) an array of signal names that the actor is currently reading, and an array of user events for each signal.

 

Then have a way for your child window to select a signal from an actor.  Maybe a right click option, or use the same menu for renaming the window.  Once a signal is selected that window could then register for the user event that corresponds to that signal selected.

 

Then back at the DAQ actor, generate a user event for each of the signals being measured when there is new data.  This way the actor is publishing, and the children are subscribing.  The publisher doesn't know how many subscribers there are and it doesn't really matter.  Unless this is done on RT I'd suggest not generating an event for each new sample of a signal, but instead generate an event and send over N samples either in an array or a waveform.

 

Then when the child gets new data, you can append this N samples to the end of the graph currently being displayed.

 

This isn't perfect and needs some through about the different supported data types, but it could scale well if done right.  This technique could be applies to non synchronous communication too.  Lets say you are looking for a CAN bus signal that is sent by another device.  You could subscribe to the data in the child window in a similar way, and then when no new data comes in, you know that signal hasn't been seen.

Share this post


Link to post
Share on other sites

When it comes to drag and drop, I found that your solution doesn't work for fast mouse dragging.

Because when dragging, other UI events will be disabled (no need for them), I found it more useful to create some while loop inside Mouse Down event that will upload front panel bounds and poll Mouse Button to check if it's up:

Drag and drop.zip

Edited by karolek

Share this post


Link to post
Share on other sites

Your upload is missing a file, luckily it was just a type def'd cluster and I could disconnect it to see how it worked.

 

From your description I didn't think I'd like a design where a while loop is inside a case of an event structure, but having it be encapsulated in a reusable subVI makes me like it for some reason.  I also don't like how this is polling in a while loop where an event structure could generate new events for a mouse move, but then again the refresh rate is configurable, and it is only for the time the mouse is down.  

 

A different design could be using the Limit Maximum instances of a mouse move event to 1.  But then that's more work in the VI using this function, where your technique is pretty easy to incorporate into a new VI.  It could be reduced even more simply by the init and close in the subVI, possibly keep the reference open with an uninitialized shift register.  You can also read the calling VI reference.  The result could be a single VI, that you put into a Mouse Down event, that takes care of a window move.  Attached is some of these improvements.

 

Thanks for sharing.

Drag Drop Hooovahh Edit.zip

  • Like 1

Share this post


Link to post
Share on other sites

Hey Guys,
 

I just accidently found this topic and its totally feasable for my Automatic Testing Project.

Unfortunately i cannot download the Multi Panel Interface.zip. Could anybody please repost it?

Best regards, Kungfu

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site, you agree to our Terms of Use.