LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Register for event on VI that's not open

Solved!
Go to solution

I have a VI that launches another VI in the background (i.e. without opening it's front panel) using Start Asynchronous Call. The front panel of the VI that is running in the background can be opened by the user. The background VI has several button that should trigger an event. Because there are so many, I've made an array of references to those buttons and passed that array to the Register for Event node. This works when the front panel of the VI is open, but when I launch the VI in the background, the Register for Event node throws error 1001: The VI front panel is not open.

 

I've attached a minimum working example to show my problem. Run 'Launch Async.vi' to see the error.

Is there a better way to register multiple buttons without having to add dozens of separate events? I don't want to bundle the buttons in a cluster because they are spread out over several tabs.

Download All
0 Kudos
Message 1 of 18
(468 Views)

You can simply delay the event registration when the "Window Opened" event occurs on the background VI, so the controls (and the front panel) are in memory when calling the registration node:

 

Download All
0 Kudos
Message 2 of 18
(460 Views)

Why not do it like this? 

johntrich1971_0-1638366317199.png

 

0 Kudos
Message 3 of 18
(452 Views)

Basjong53 explained why:


@Basjong53 wrote:

Because there are so many, I've made an array of references to those buttons and passed that array to the Register for Event node.

If there are too many controls, the case label does not show all control names and adding manually all cases is tedious, so getting an array of all buttons and registering dynamically is a better option.

0 Kudos
Message 4 of 18
(448 Views)

Put an invoke node 'Front Panel.Open' before the event registration and set the state to hidden. The front panel will open, but not visible for the user. If you want to show the panel to the user use the same invoke node with 'Standard' for state.

Message 5 of 18
(429 Views)

@raphschru wrote:

Basjong53 explained why:


@Basjong53 wrote:

Because there are so many, I've made an array of references to those buttons and passed that array to the Register for Event node.

If there are too many controls, the case label does not show all control names and adding manually all cases is tedious, so getting an array of all buttons and registering dynamically is a better option.


Fair enough on not showing all the control names. I still prefer that approach to the tedious task of manually creating all of the references and putting them in the array, but I understand that it's a matter of personal preference. One could use the subdiagram label to note all of the buttons that are handled by the case.

0 Kudos
Message 6 of 18
(415 Views)

@UliB wrote:

Put an invoke node 'Front Panel.Open' before the event registration and set the state to hidden. The front panel will open, but not visible for the user. If you want to show the panel to the user use the same invoke node with 'Standard' for state.


Thank you for the suggestion, this does work. However, what if I want to show the background VI in a subpanel? Setting the FP.Open methods to Standard opens a new window, not in the subpanel.

@raphschru wrote:

You can simply delay the event registration when the "Window Opened" event occurs on the background VI, so the controls (and the front panel) are in memory when calling the registration node:


This seems a good solution, however I don't see the event 'Window Opened' when I select "Application"??


@johntrich1971 wrote:

@raphschru wrote:

Basjong53 explained why:


@Basjong53 wrote:

Because there are so many, I've made an array of references to those buttons and passed that array to the Register for Event node.

If there are too many controls, the case label does not show all control names and adding manually all cases is tedious, so getting an array of all buttons and registering dynamically is a better option.


Fair enough on not showing all the control names. I still prefer that approach to the tedious task of manually creating all of the references and putting them in the array, but I understand that it's a matter of personal preference. One could use the subdiagram label to note all of the buttons that are handled by the case.


I have to make the array anyway to determine which of the buttons has been pressed. I seach the ctlref in the array of button references.

0 Kudos
Message 7 of 18
(386 Views)

The MGI Panel Manager toolkit may help with this. It encapsulates a lot of the somewhat frustrating panel management tasks. I personally use it with the Actor Framework for everything I do with front panels, but it should work just fine without it.

 

It will let you show/hide/move the panel around with methods instead of VI Server calls, and will give you access to certain events that let you initialize properly. For example, you should be able to handle an event case when the panel is Shown that will register your other events. This will then fire when you show it in a subpanel, or as a popup, or whatever.

 

I think you can also simply use the This VI-> Panel Resize event to catch when the panel is opened, then register your events in there. I haven't tried this one though.

0 Kudos
Message 8 of 18
(382 Views)

OOps "Window Opened" is a private event which is not accessible with a standard LV config (and not recommended to use).

 

Since you cannot detect the opening of the front panel with an event, you will have to pass a command (using a message queue) to the background VI right after you insert it in the subpanel to make the registration.

 

Concerning the array of buttons done by hand, you could also iterate through the Controls[] property of the Front Panel and filter only the needed controls (by class or name).

0 Kudos
Message 9 of 18
(376 Views)

@Basjong53 wrote:


I have to make the array anyway to determine which of the buttons has been pressed. I seach the ctlref in the array of button references.


That's one of the nice things about the event structure - it reports a control reference for the control if the control reference is needed, and if there are multiple controls for that event it will only return a reference for the control that triggered the event. 

 

Edited to add: I just reread your response. I'm not following why you need to search the array. Do you have a case structure inside the event structure that runs different code depending upon the control? Perhaps you could use the control name instead of an index in the array. This would be more scalable and easier to read in the future.

0 Kudos
Message 10 of 18
(374 Views)