LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Keyboard "tab" control in Array of Clusters

Solved!
Go to solution

I'm trying to polish some of my LabVIEW user interfaces so that my users can work faster in them and so that they follow more "Windows UI Standards" (or whatever).

 

I have an array of clusters.  The cluster has 3 numerics.

 

When a user "focusses" on the first numeric within a cluster and hits the tab key, it moves the focus to the second numeric.  Hit tab again, and it jumps to the 3rd numeric.  Hit the tab key a 3rd time and it jumps back to the first numeric in the cluster.  What I want to happen is for the focus to move to the first numeric in the next element of the array.

 

I've started to play around with the "Key Down" event case that has a conditional looking for "TAB" and then checks the "FindCtrlWithKeyFocus" with the last numeric.  My probes within this event show that the "TAB" key detection is working, but the "FindCtrlWithKeyFocus" never has a TRUE output from the "CtrlFound?" output of the Invoke Node.

 

Even if I did know if tab was pressed in the last element, I'm not real sure how to move focus to the first numeric within the next cluster element of the array.

 

A numeric array behaves in the correct way.  I could get the program working the way I want with a 2d array of numerics.  However, each numeric has different data entry parameters and there is also a lost of "self documentation".  I would like to find a solution because this has come up with other, more complex, array of clusters that would not be solveable with a 2d array of a base type.

 

Seems overly complicated to me.

 

Bonus Question: The default value of my numerics is 0.  When my user clicks a numeric the cursor is on either side of the 0 and the user has to delete the 0 prior to their data input.  When a numeric is entered via the Tab key, the whole field is selected.  When the whole field is selected, whatever the user inputs will replace the original "0" that was in the field.  Anyway to have the whole field selected when the user uses the mouse?

 

Sorry for the wall-of-text post (and the preposition hell).  Thanks for your input.

0 Kudos
Message 1 of 10
(8,575 Views)

I've had similar problems in the past and I've posted my solution over at the LAVA forum.

 

http://lavag.org/topic/12431-how-can-i-catch-the-key-pressed-on-an-object-contained-in-a-cluster-ele...

 

As I stated over there this is the only solution I know of but it is not a very good one.  I wanted to be able to select key focus on each item in an array, but couldn't so I created several strings which appeared to be an array, then I could control each one individividually.  There was alot of extra logic involved to get an array of strings as the output and have the scroll bar working right.

 

I'm hoping someone here has a better solution but it works for a basic array of stings, so I figure it would also work in your case with some modifications.

0 Kudos
Message 2 of 10
(8,546 Views)

Thanks for the reply Hooovahh!

 

I was considering a similar solution but do not want to face the extra amount of coding it would take to accomplish this.

 

I'll try your solution and see how it goes, but I'm looking for something that I can apply across multiple application that I'm building right now that are data entry intensive.  Maybe LabVIEW just isn't the right platform to do these things in (but there is also hardware control involved, and it is what I know best so I think it is all I have to work with).

 

I've been trying to think of a better way to accomplish my goal.  One thought is to have a stand-alone cluster above my array as a "new data entry" type control and the last element of the cluster is a button with a label: "add".  That way the user can tab-through the data entry cluster and when they get to the "add" button they can hit space, and the next tab will take them to the beginning of the data entry cluster.  At least that way the user can enter their data without having to go back and forth between mouse and keyboard.

 

idk.... i'm going to check idea exchange to see if someone has already posted this.  Seems like if a cluster is part of an array, the behaviour for the TAB key should be more sophisticated as its default behavior.  I'll post something if it isn't there already.

0 Kudos
Message 3 of 10
(8,530 Views)

A few points:

 

1) the VI-scope method FindCtrlWithKeyFocus apparently doesn't look inside of container controls (only what you can tab around to), but that doesn't mean that some inner control doesn't have keyfocus.

2) it is possible to use references & property nodes to find out which control does have keyfocus.

3) I don't think there's a way to set keyfocus to a control in a different element of an array.

 

but there's good news.  LV does provide a way to navigate through arrays with the keyboard.  In the help under "Tabbing through the elements of an Array or Cluster":

 

 

Tabbing through Elements of an Array or Cluster 
Complete the following steps to use the <Tab> key to move through elements within a single array or cluster when you run a VI. 

Display the front panel. While the VI is running, press the <Tab> key until the array or cluster is highlighted. 
Press the <Ctrl> key and the down arrow key to move the key focus inside the array or cluster. (Mac OS) Press the <Command> key. (Linux) Press the <Alt> key. 
Press the <Tab> key to sequence through the array or cluster elements and the array indexes. 
To return to tabbing among front panel controls, press the <Ctrl> key and the up arrow key. (Mac OS) Press the <Command> key. (Linux) Press the <Alt> key. 

 

 

I also wrote a quick event case for the mouse down event on an array of clusters of digital controls that gives select-all keyfocus on the element clicked.

 

 

-Barrett
CLD
Message 4 of 10
(8,515 Views)
Solution
Accepted by topic author hecmar.arreola

and a snippet, if that's more useful for some:

 

18309i45B96FE4CEE3E7E3

-Barrett
CLD
Message 5 of 10
(8,507 Views)

Thank you for the post blawson!

 

That select all event code you posted was definitely what I was looking for! 

 

I am still kind of dis-satisfied with what NI has setup as the way to tab through a front panel.... it really isn't very intuitive IMHO.  Oh well, I'm glad that at least the behavior isn't a bug per-say and that NI has considered the problem.  But I will still post in the idea exchange the alternative behavior that I would like to see (and think it is more intuitive, at least for my application).

 

Cheers!

 

-Nic

0 Kudos
Message 6 of 10
(8,488 Views)

Well I've gone and gotten the tabbing behavior you're looking for.

 

-the key is to set "skip when tabbing" on the controls inside the clusters to true, and leave it false for the array elements.  Now when keyfocus is on one of the cluster controls and Tab is pressed, LV will put the keyfocus on the next visible array element.

-then use a "key down?" filtering event to check and see if any of those controls have keyfocus when Tab is pressed.  If so, and it's not the last control in the cluster, discard the keypress and programmatically advance keyfocus to the next item.  

-Finally if the Tab press was not discarded, use a normal "key down" UI event to check if one of the array elements now has keyfocus and if so, set KF to the first control in its array.

 

So in short, this setup turns off tabbing along a row so that every tab will move to the next row.  Then it filters out Tab if it's not yet at the end of the row.  Finally, it automatically puts the cursor in the first column when the row has advanced.

 

 

One significant drawback is that it only tabs between visible array elements.  You can probably make it auto scroll.

 

I'll leave it as an exercise for the reader to handle the shift+Tab (reverse tabbing) key presses.

 

18327i355A4434D1B311B1

 

To me, this runs up against three holes in LV UI programming:

1) Array Element events should be available.     The Array:Key Down event only handles key presses when the array has keyfocus, not when things inside it do.  Any kind of key filtering has to be done at the VI level (!!!).

    The data source for these events should include the element index (eg what cell was clicked on?)

 

2) There aren't effective ways in VI server to deal with individual array elements.  I recognize that some of it is the basis that array elements have the same properties, but there are display and selection properties that do differ between cells.  I ought to be able to specify that a particular cell index has keyfocus.  Arrays, why can't you be more like Tables?

 

3)Tab order should be flat, not hierarchical.

 

 

edit: in case the snippet messes things up, file is attached.

-Barrett
CLD
Message 7 of 10
(8,469 Views)

blawson - you are too cool.  Thanks for all the help man!  I (and my users) thank you!

0 Kudos
Message 8 of 10
(8,439 Views)

Does it have to be this advanced? My idea (I haven't tried it) is that Keydown? sends on all tabs, except if you're at the last element of the cluster, in which case you generate a +1 to array index.

 

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 9 of 10
(8,419 Views)

ok here it is FAR simpler, using "dynamic" event registration.  Basically the event registration lets us create event cases for anything we can create a reference for.  If you use a reference to an array element, it catches the event(s) registered for any of those elements.  Why this is not available in the basic events menu is beyond me.

 

The strategy in the following VI is to catch tab key-downs in the last control of the cluster's "row".  using a filter event, we turn off tabbing before the key is processed.  when the key is processed, we get references to the cluster's controls again, turn tabbing back on and set keyfocus on the first one.

 

Yamaeda, the answer to your suggestion is that generating a "+1 to array index" isn't possible.

 

18427iFF85D5C413AEFDF1

-Barrett
CLD
Message 10 of 10
(8,388 Views)