Jump to content

Multi Panel Interface


Recommended Posts

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.

Link to comment
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
Link to comment
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.

Link to comment
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.

Link to comment
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
Link to comment

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
Link to comment
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.

Link to comment
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.

Link to comment
  • 1 year later...

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. 

Link to comment

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.

Link to comment

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.

Link to comment

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
Link to comment

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.

Link to comment

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 ?

Link to comment

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.

Link to comment
  • 2 weeks later...

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. 

Link to comment

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.

Link to comment
  • 6 months later...

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
Link to comment

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
Link to comment
  • 1 year later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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