MarkCG Posted November 4, 2015 Report Share Posted November 4, 2015 Hi all, as the complexity of some of the systems I have worked on grew, I found that I could have dozens of user controls in my diagrams, handled by an event structure. Almost all of the case structure cases handled "value change" events and simply enqueue the new value and a "X changed" type command to the appropriate module or remote target. Having 80 cases in an event structure, all doing more or less the same thing seems like it's crying out for refactoring. I came up with attached class in order to capture UI command-value pairs and write them to a network stream, using just one case of a case of the event structure. It leads to a lot less code repetition (at the expense of some more BD real estate on the left hand side) but I am more or less happy with it because it's less wiring overall. I made an example (attached) to demonstrate it. What do you all think of this way of structuring my UI code? What improvements could be made? Quote Link to comment
ssingh1 Posted November 5, 2015 Report Share Posted November 5, 2015 Good work but Attachment not found in the post. Quote Link to comment
drjdpowell Posted November 5, 2015 Report Share Posted November 5, 2015 Your code was not attached, but I often use variants, dynamic registration of arrays of control references, and control labels that encode the message that needs to be sent, as illustrated in this old post. I also done similar things connecting multiple controls with Camera Attributes or DAQmx channels. 1 Quote Link to comment
MarkCG Posted November 5, 2015 Author Report Share Posted November 5, 2015 Derp! Ok this should be attached. Yes I have used control refs to do this. Control-Value-Command Registry Example.zip Quote Link to comment
shoneill Posted November 6, 2015 Report Share Posted November 6, 2015 I too have done different things to better handle this kind of scenario. Recently my interest has beek piqued by the possibility of using callback VIs for registering the Events rather than using the Event structure itself. The advantage of this? You can split the handling of the events among different levels of an object inheritance chain. This method couples well with the command pattern for the receiving end. Advantages: Essentially allows us to split up individual frames of the Event structure into individual (boiler-plate) VIs. Disadvantages: Knowing somehow that the events are being handled somewhere and that the callback VIs themselves run int he root thread. Quote Link to comment
Jordan Kuehn Posted November 6, 2015 Report Share Posted November 6, 2015 I too have done different things to better handle this kind of scenario. Recently my interest has beek piqued by the possibility of using callback VIs for registering the Events rather than using the Event structure itself. The advantage of this? You can split the handling of the events among different levels of an object inheritance chain. This method couples well with the command pattern for the receiving end. Advantages: Essentially allows us to split up individual frames of the Event structure into individual (boiler-plate) VIs. Disadvantages: Knowing somehow that the events are being handled somewhere and that the callback VIs themselves run int he root thread. I can see the benefit to this, but callback VIs seem to obfuscate the code greatly to me, as you mention in your disadvantages list. Quote Link to comment
shoneill Posted November 6, 2015 Report Share Posted November 6, 2015 The code obfuscation is really an annoying (and very serious and real) part of the implementation. It is enough to stop me applying the idea in a widespread manner because the cost of debugging can be large. The only other thing I could think of woule to implement the callback VIs with LVOOP and have the parent optionally include some debugging information which cen be centrally logged / viewed / sorted. I believe it could be solvable but my 24 hour days don't give me enough time to come close to doing such an idea justice. Quote Link to comment
drjdpowell Posted November 6, 2015 Report Share Posted November 6, 2015 I tried having call-backs that called methods on a LVOOP object inside a DVR. It worked, except that occasionally two events happening at about the same time caused the UI to freeze, possibly due to some kind of lock-up involving the DVR and the UI thread in which the callbacks run. This was near impossible to debug, and I abandoned callbacks in favor of an asynchronous VI that handled events with an Event Structure (calling the same LVOOP object held in a shift register). Quote Link to comment
shoneill Posted November 6, 2015 Report Share Posted November 6, 2015 Reminds me of another method I've used in the past where I group lots of functionally similar events and place each group in it's own event structure, blatantly disregarding the general idea to not have move than one event structure in your code.... At least that way I could remove and add new functional groups without having to touch other event structures. Quote Link to comment
ShaunR Posted November 6, 2015 Report Share Posted November 6, 2015 blatantly disregarding the general idea to not have move than one event structure in your code.... That is one event structure in a block diagram, surely? Quote Link to comment
shoneill Posted November 6, 2015 Report Share Posted November 6, 2015 I always thought they meant one event structure per loop myself.... But yeah, I believe it is meant as one per Block Diagram. Quote Link to comment
Neil Pate Posted November 6, 2015 Report Share Posted November 6, 2015 I think it is safe to have multiple Event Structures in the same VI as long as they are configured to respond to different events. I have used this technique where I have one Event Structure to handle all User Events, and another to handle User Interface Events. Quote Link to comment
MarkCG Posted November 7, 2015 Author Report Share Posted November 7, 2015 Your code was not attached, but I often use variants, dynamic registration of arrays of control references, and control labels that encode the message that needs to be sent, as illustrated in this old post. I also done similar things connecting multiple controls with Camera Attributes or DAQmx channels. Yep this is pretty much what it is, as shown in that thread. I just made the message name independent of the control name. I also found that sometimes I wanted to associate a particular message name to a particular value of the control. For example: Log button becoming true sends "Start Logging" command, Log button becoming false send "Stop Logging" command. The thing I like about this is that I can handle fiddly "stateful" control logic inside XControls. The Xcontrol has an enum value and I can register a particular enum value to a command specific command message. For example, a "tape deck " type control with play, pause, resume and stop / abort buttons. Three button, four messages "Play" "Pause" "Resume" and "Stop". The X control logic wraps the "button logic" up nicely without having to smear it over 4 cases of you main UI's event structure. Advantages: Essentially allows us to split up individual frames of the Event structure into individual (boiler-plate) VIs. Disadvantages: Knowing somehow that the events are being handled somewhere and that the callback VIs themselves run int he root thread. So now would you have 80 boilerplate VIs instead of 80 event structure cases? Quote Link to comment
drjdpowell Posted November 7, 2015 Report Share Posted November 7, 2015 For example: Log button becoming true sends "Start Logging" command, Log button becoming false send "Stop Logging" command. The thing I like about this is that I can handle fiddly "stateful" control logic inside XControls. The Xcontrol has an enum value and I can register a particular enum value to a command specific command message. For example, a "tape deck " type control with play, pause, resume and stop / abort buttons. Three button, four messages "Play" "Pause" "Resume" and "Stop". The X control logic wraps the "button logic" up nicely without having to smear it over 4 cases of you main UI's event structure. I solve this issue a different way, by making my messages all "control-likeâ€: a label and a value. So I would have messages: “Set Loggingâ€, a boolean that is True or False “Set Play Stateâ€, a string (or possibly enum) with values "Play" "Pause" "Resume" or "Stop" Quote Link to comment
bublina Posted November 7, 2015 Report Share Posted November 7, 2015 Mark, does this mean you have 80 controls on your FP? If this is the case for me, the controls ussually correspond to each other or not, so you put them into clusters, then you just register the value change for cluster. Once the event happens, the left Event nodes will give you Old + New value, so compare, this gives you the index of the control changed, get the control reference out of the cluster, read it's name and wire it to the case structure. Now you have 8 event cases where each has case struct with 10 cases named by the controls. Works fine for me and makes the BD more readable. Event.vi Quote Link to comment
bublina Posted November 7, 2015 Report Share Posted November 7, 2015 After re-reading your problem, I guess this approach is better. Make an array that translates the control names and possible values into messages (or whatever data you use to control your program further). I use this approach as well, cool thing is that all translations are LabVIEW data, so you can make your own code to add new dictionary entries, so change to FP means you will just need to run some VI that will populate/change the array and you can script your own code to do that. Event.vi Translator.vi Quote Link to comment
shoneill Posted November 9, 2015 Report Share Posted November 9, 2015 So now would you have 80 boilerplate VIs instead of 80 event structure cases? No, of course not. You would need one single VI per datatype you are registering events for. If not everything is a typedef, this tends to not be too many VIs. Of course there would be 80 VIs in memory (callback VIs), but not 80 VIs on disk. Quote Link to comment
MarkCG Posted November 10, 2015 Author Report Share Posted November 10, 2015 Mark, does this mean you have 80 controls on your FP? If this is the case for me, the controls ussually correspond to each other or not, so you put them into clusters, then you just register the value change for cluster. Once the event happens, the left Event nodes will give you Old + New value, so compare, this gives you the index of the control changed, get the control reference out of the cluster, read it's name and wire it to the case structure. Now you have 8 event cases where each has case struct with 10 cases named by the controls. Works fine for me and makes the BD more readable. Hi bublina yes I definitely use clusters for parameters that are related. I just look for a cluster change event and send the whole cluster if just one element has changed though, I typically don't care which one has changed. So if I had a cluster of PID loop gains on the front panel, I would just send a message called "PID loop gain changed" whenever the proportional, integral, or derivative gains where twiddled. After re-reading your problem, I guess this approach is better. Make an array that translates the control names and possible values into messages (or whatever data you use to control your program further). I use this approach as well, cool thing is that all translations are LabVIEW data, so you can make your own code to add new dictionary entries, so change to FP means you will just need to run some VI that will populate/change the array and you can script your own code to do that. good to see I'm not the only one thinking this way! Yes I chose to implement he dictionary is a variant hash, I just like being able to look up any kind of data with a string instead of iterating through an array. Probably is a wash performance wise. No, of course not. You would need one single VI per datatype you are registering events for. If not everything is a typedef, this tends to not be too many VIs. Of course there would be 80 VIs in memory (callback VIs), but not 80 VIs on disk ah ok makes sense. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.