LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Array of Cluster Dynamic Event causes strange UI behavior

I have a front panel control that is an array of cluster type, and I ultimately want to run different code depending on which cluster element was changed. I started out with a value change event for the whole array, then comparing new/old values to find the element that actually changed. But as I added more elements to the cluster, that code got increasingly hard to read, and I decided to try something else. I used control references for each element in the cluster and registered for events on those elements. In my particular application, I don't necessarily need to know the array index of the change, just which element in the cluster was changed, so this approach works fairly well. But something weird happened: if I start with an empty array, and then enter a value into one of the controls in the cluster, instead of creating a new element in the array, it looks like only the default value of the array is changing, and the array remains empty. On further investigation, I found that if I dynamically register for a value change event for the whole array, and then use a local variable to read and re-write the whole array value, then the UI behaves as expected. I'm thinking this is a bug, but I figured I'd check here first and see if anyone else knows anything. I've included an example that demonstrates the behavior, and I'm using LabVIEW 2013.

Message 1 of 9
(3,728 Views)

I don't think you have a bug.  I think your string reference isn't what you think it is.

 

A reference to an array element isn't a reference to a specific element in a specific index of the array.  An array element is a reference to the definition of the elements of the array.  In other words, there is no reference to an element at index 1, or an element at index 2.  The reference is to the baseline structure of an array.

 

I think you are lucky if your read array, write back to the array works.  I wouldn't trust it.  I think you are just happening to take advantage of a race condition that the array gets updated at the instant you hit enter, then the value change event occurs.  I can't quite explain why array resets itself back to empty.  But it just seems like you are using the events of individual array or cluster elements in a way they weren't meant to be used.

0 Kudos
Message 2 of 9
(3,704 Views)

At first I was going with what Ravenfan said but then I played a bit and there is something that does not settle well with me.

 

Just concentrating on the "Magic" option for now...

 

1) Make sure the array of clusters is empty.

2) Create an indictor for both the Old and New values and size them up to see more than one cluster.

3) Run the VI

4) Click in the string2 of the second array element and enter a value and commit the change.

 

The array is empty!

 

Should have created a default cluster for the first element in the array and added the cluster for the second element in the array.

 

What am I missing?

 

Start again with the array empty.

 

Right-click just below the bottom right corner of the "String 2" control of the second element and select "insert Element before".

 

The array updates with two elements as I expect but the "oldVal" and "NewVal" only have one element in them.

 

Riddle me that batman!

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 3 of 9
(3,688 Views)

I think I would say "Don't Do That!".  Let's start with a simple Array of Integers, say 1 to 10.  Let's say I have a Value Change Event for this Array, and I change "6" to "16".  Bang, the Value Change Event fires, telling me that "there is something different about this Array".  But if I want to know which Array Element has changed, I have to compare "1" to "1", "2" to "2", and eventually I'll compare "6" to "16", and can say "I found it!".

 

Now, make the Array an Array of Clusters, say with 10 elements each.  First, I need to discover which Array Element has the "new" data, and then I need to decide which Cluster Element was changed!  What a pain!

 

Maybe rethink how you are organizing your Front Panel controls?

 

Bob Schor

0 Kudos
Message 4 of 9
(3,670 Views)

@Bob_Schor wrote:

Now, make the Array an Array of Clusters, say with 10 elements each.  First, I need to discover which Array Element has the "new" data, and then I need to decide which Cluster Element was changed!  What a pain!

 

Maybe rethink how you are organizing your Front Panel controls?

 

Bob Schor


Actually this is exactly what the event cases for cluster elements should help with. Since I have separate event registration terminals for each cluster element, I can handle them in separate event cases, so at most I would need to figure out the index. And like I said, for my application the index turns out not to be so important anyway.

 

I'm certainly happy to rethink the front panel organization, but for this kind of problem I haven't seen solutions that seem any less clunky than what I'm doing. In reference to the example VI, suppose that String 1 and String 2 are both properties of the same thing, like if String 1 was someone's name and String 2 was email address. If I'm dealing with a list of people, I should generally have the same number of names as email addresses, each name is associated with one and only one email address, and some how or other I'd like the UI to reflect that.

 

What I've seen is something along the lines of a single cluster control (or just individual controls grouped together), an array associated with each control that has a simple, non-cluster datatype kept in memory and then a numeric "index" control with value change events to pull matching values out of each simple array. But if you want scroll bars, or you want to show more than one array element at a time, there's substantial extra development on the back end. And if you users to be able to add or remove array elements, generally there is extra coding to do for that, too.

The other option I've seen is doing exactly what you are advising against here, where there's just a value change on the top level array, and the event case has to look through it and find what actually changed.

0 Kudos
Message 5 of 9
(3,664 Views)

Yeah, this is what I was really getting at. If you want to boil the bug down to it's barest essence, you could take out the Array event case, and not register for the Array value change, just for the two strings. At that point the event structure would just have the timeout case. But even though there would be no LabVIEW code executing due to the dynamic events firing, it looks like just registering for them is changing the UI behavior in a way that an end user will definitely notice. That, to me, seems odd.

0 Kudos
Message 6 of 9
(3,661 Views)

Tossing the two "register for event" inputs used for the strings fixes things.

 

I suspect what you were seeing was the result of having events registerd but no event case to service those events.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 7 of 9
(3,636 Views)

@RavensFan wrote:

I don't think you have a bug.  I think your string reference isn't what you think it is.

 

A reference to an array element isn't a reference to a specific element in a specific index of the array.  An array element is a reference to the definition of the elements of the array.  In other words, there is no reference to an element at index 1, or an element at index 2.  The reference is to the baseline structure of an array.

 


AFAIK this isn't strictly true.  If you have a control reference to a String in an array you can read and write to it whenever you want BUT the trick is knowing WHICH element of the array your reference is pointing to.

 

If you have an array with only a single element visible, things are simple, the control you've registered for is the control you can see.  Handling arrays with multiple visible elements is tricky but there's a really ugly workaround.  Set the index of the array to the object you want to modify, set the number of visible elements to 1 in each dimension (X and Y) and then make your changes.  When finished, reset the values of the array (index and visible items).

 

I'm not saying it's a good idea to do this (it's not) but it allows some portion of determinism as to which control your "Array element" reference is pointing to.  IIRC if you don't trick around like this, the reference will be to the last active cell of the array.  By limiting to a single element visible, you can force this to be the array element you want.

 

Completely trivial and useless information.

0 Kudos
Message 8 of 9
(3,618 Views)

For the morbidly curious:

 

If I add event cases for those two strings, those events don't fire when things are added or removed from the array (although there is a value change for the array control itself). That actually makes a certain kind of sense to me, I guess. But it does make the original behavior a little more irksome, because it means that registering for the event is impacting user actions which don't fire the events that I'm even registering for.

0 Kudos
Message 9 of 9
(3,600 Views)