Jump to content

Focus persistence between VI calls


mje

Recommended Posts

So here's another fun little behavior related to control focus.

 

Consider a VI with a loop containing an event structure statically linked to the value change events of controls: alpha and beta. Alpha is some type of editable control like a string, and beta is a boolean configured to have a key binding. The value change event of beta terminates the loop. Beta is not configured to receive the key focus when the key binding is used.

 

Scenario 1:

 

Open the VI and run it from its front panel. While editing alpha, use the key binding for beta.

 

The key binding triggers the value change event for beta, which causes the loop to return. We never see the last alpha value change event because the alpha control never lost focus, thus the value was never changed. Nothing alarming here as the beta control is configured to produce this exact behavior.

 

Scenario 2:

 

Call the VI consecutively from another VI. On the first call, while editing alpha, use the key binding for beta.

 

The first call to our VI starts, and as before when editing alpha, beta's value change event executes, causing the first call to return.

 

Now things get interesting. The second call to the VI starts, lo and behold the first thing we get is a value change event from alpha containing the data that was being entered on the previous call to the VI.

 

Probably best demonstrated in a three and a half minute video.

 

As far as I can tell this happens because on start up the VI clears the focus from alpha, therefore triggering a value change event from data that was entered on the previous call. Is this really desired behavior though? I think the expected behavior for most people would be all the setup mechanics of the window, including the initial control focus would be done before events are being generated.

 

The example VI shown in the video is attached (LV2013): dialog.vi

Link to comment

At first this might seem as odd behaviour, but if you think of it - it is just as event structures work. They queue events to be handled whenever the structure is called, and this queue is made when the VI containing evstr enters running state. Now, if you close this VI before all the events are handled, there would be some leftovers in the events queue (that's also one reason why we should unregister dynamic events when leaving VI with evstr). You can easily see this in Event Inspector Window (very neat tool in 2013 by the way). And that would be something I'd expect - if I'd treat event structure as simple FIFO, I wouldn't want it to lose any data I put into it, so I expect to get next event the next time I call this particular structure. Of course, only if this VI would never leave memory during the application run - I strongly believe that making dynamic calls to this VI and closing its reference afterwards would also clear the events queue (easy to check, I just don't have time for it right now).

For more fun: If you make this VI preallocated clone reentrant, you can be sure that there is new events queue for each clone. If you'd make it shared clone, you might, or might not, come across one that already has something waiting to be handled.

 

However, I can see other issue there, and that is the order of events. I've seen many strange cases where order of events were just not as I would expect it - i.e. the value change of one control called after, not before, mouse down event on other control (this is kind of unfixable issue in one of my applications). This is one of those cases, I think the right order should be value change on focused control first, and then value change on the one with key binding.

Edited by PiDi
Link to comment
  • 1 year later...

I just came across this while cleaning up old code so I thought I'd resurrect the thread and maybe get some more discussion this time around. I'm not satisfied this is good behavior.

 

For the second call of the VI to generate an event that essentially originates from actions taken on the VI from the first call (or perhaps worse, an event from the first call being handled in the second call) seems to violate some form of encapsulation, but I can't quite pin down the right terminology.

 

Yes, reentrancy would eliminate the issue, but I think something is fundamentally wrong with the build-up and tear-down mechanics of static event registration.

Link to comment

When using a string control the easy solution is to right click and enable "Update While Typing" which will trigger a value change with every key stroke.  Then hitting return for the key binding on the button will still have the last typed char on the string control.  Other controls don't have this problem as often, because if I tab into a enum, pressing up or down, triggers the value change and should be fine.

 

There are other controls that there isn't an easy workaround like this.  One case is like with a VISA Resource name.  If the user tabs into the control, and types COM0 then hits return, then the value change won't be triggered, and because it isn't a string, there is no update while typing like a string.

Link to comment

I just came across this while cleaning up old code so I thought I'd resurrect the thread and maybe get some more discussion this time around. I'm not satisfied this is good behavior.

 

For the second call of the VI to generate an event that essentially originates from actions taken on the VI from the first call (or perhaps worse, an event from the first call being handled in the second call) seems to violate some form of encapsulation, but I can't quite pin down the right terminology.

 

Yes, reentrancy would eliminate the issue, but I think something is fundamentally wrong with the build-up and tear-down mechanics of static event registration.

 

LabVIEW FPs have been needing a revamp for years (silver controls were a placebo). Anecdotally, and exaggerating only slightly, an application will require 2 days to code the hard parts and 2 weeks for the UI with a vast majority of bugs being usability issues.

 

I have exclusively moved away from LabVIEW front panels and now use a browser for all commercial LabVIEW applications. Until such times as they fix and enable completely customisable controls for look, feel and behaviour; I don't see that changing any time soon.

Edited by ShaunR
  • Like 2
Link to comment

My pet peeve is the numeric control. I would love to have an "update value while typing" property like for string controls. When the user type a value and then click on a button that triggers a read of the value, we get the old value. We work around this by forcing a the control to lose the key focus first, but that's less than ideal...

Link to comment

For the second call of the VI to generate an event that essentially originates from actions taken on the VI from the first call (or perhaps worse, an event from the first call being handled in the second call) seems to violate some form of encapsulation, but I can't quite pin down the right terminology.

 

I'm not sure whether I agree or not, but as PiDi pointed out, the behavior is at least consistent - the registration for a static event happens when the VI enters run mode (not when it's actually running). From that point on it will enqueue all events until it goes idle. This explains why it remembers the event from the last run - the VI is still in run mode. I personally also had this issue with certain users who would double click an OK button (users. :angry: Am I right?). They would sometimes be fast enough for LV to register this as two value change events and the next time around the dialog would be dismissed immediately.

 

Anyway, another way to solve this is with dynamic registration - register when the VI starts and unregister when it ends. This is more of a PITA, but it does work.

Link to comment

My pet peeve is the numeric control. I would love to have an "update value while typing" property like for string controls. 

Now that I think about it I remember a possible work around for numeric controls.  While the value change doesn't get triggered for numeric control, the Numeric Text >> Text property node will return the updated value.  So if the user enters "12.34" in a numeric control and hits enter, causing a value change on the key binded boolean, the value of the numeric won't have been updated yet, but by reading the Numeric Text >> Text you can find what the user entered and convert that to a floating point numeric.  It sucks sure, but I think in simple cases it is easier than catching Key Down? looking for returns, focused controls, or registering user events.

Link to comment

I'm not sure whether I agree or not, but as PiDi pointed out, the behavior is at least consistent - the registration for a static event happens when the VI enters run mode (not when it's actually running). From that point on it will enqueue all events until it goes idle. This explains why it remembers the event from the last run - the VI is still in run mode. I personally also had this issue with certain users who would double click an OK button (users. :angry: Am I right?). They would sometimes be fast enough for LV to register this as two value change events and the next time around the dialog would be dismissed immediately.

 

Anyway, another way to solve this is with dynamic registration - register when the VI starts and unregister when it ends. This is more of a PITA, but it does work.

 

Yep, the behavior is consistent. I had a good idea of what was going on even in the original post. It's very subtle and when I tracked a bug down last year to this, I was left wondering how many odd behaviors of my previous applications could be explained by this. There are many ways to insure against this behavior, but that wasn't the point of the thread-- I think we can all work our way out of this situation once we identify the cause.

 

I understand the distinction between execution and run mode, and how that pertains to static event registration. We know VIs have state data, that's how control data persists between calls, uninitialized shift registers work, etc. However never in my years of experience had I ever seen any example where changes that happen while my diagram is not executing could generate events to be consumed during execution.

 

It has made me rethink how I think about static events. The lifespan of static event registration is fundamentally inconsistent with how I've been treating event context in my dialog VIs. I may very well adopt practice of using only dynamic event registration just so I can be in absolute control over the lifetime of the registration.

Link to comment

It has made me rethink how I think about static events. The lifespan of static event registration is fundamentally inconsistent with how I've been treating event context in my dialog VIs. I may very well adopt practice of using only dynamic event registration just so I can be in absolute control over the lifetime of the registration.

The new Flush Events primitive may also work for dialogs.

However never in my years of experience had I ever seen any example where changes that happen while my diagram is not executing could generate events to be consumed during execution.

I’ve used this behavior with Event Structures inside Custom Probes, where events can be generated even though the probe is only actually executing periodically.  XControls work similarly, I think.

Link to comment

Join the conversation

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

Guest
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.