ValueChanged event not fired on uieditfield when setting property Value
이전 댓글 표시
Hi
I have a uieditfield:
u = uieditfield();
The I attach a listener to the ValueChangedFcn
u.ValueChangedFcn = @(s,e)disp(e);
If I type into the edit field the my listener gets called as expected. But if I set the property directly
u.Value = '2';
no event is fired.
Is there something wrong with what I am doing or with Matlab?
댓글 수: 5
Adam
2019년 1월 10일
As far as I am aware those callbacks only trigger when the field is changed in the UI, not programmatically. That is the case with older ui components.
Andreas Klotzek
2019년 1월 10일
Adam
2019년 1월 10일
If you are familiar with object-oriented programming you could create a simple wrapper class around your uieditfield as an interface through which you access it programmatically, then within the class functions you can trigger events when the value is set. It can be done with just functions too I guess, but less easily.
I don't know if there is an alternative for uieditfield or whether it is planned to open up this functionality in future since it is still very much under development.
J. Alex Lee
2020년 4월 24일
Is this a concious decision based on some programming principle? It seems to me the more obvious/expected behavior is that changing the "Value", no matter how, triggers the "ValueChangedFcn"...otherwise they should have called it the "UIElementManipulatedFcn"...
I understand the wrapper concept as suggested by Adam and demonstrated by Jan, but it seems a cumbersome solution especially if you want to ensure your event object looks the same as it does from the manipulation of the ui element, and you want to do this for many types of ui elements...
Am I missing something?
Rob Campbell
2022년 12월 22일
I agree. This is weird and differs from how this works in a Figure vs a UI.
답변 (2개)
You can write a wrapper for setting the value programmatically, which calls the callback manually:
function SetMyValue(objectH, Value)
objectH.Value = Value;
myEvent.Origin = 'Value set programmatically';
objectH.ValueChangedFcn(objectH, myEvent);
end
댓글 수: 9
Andreas Klotzek
2019년 1월 11일
Jan
2019년 1월 11일
So what the the actual problem you want to solve?
cedric manoury
2020년 10월 21일
Hi all,
Thanls Jan, it exactly solve my problem !
Nathaniel Allan-Rahill
2021년 11월 11일
I agree with @Andreas Klotzek. I appreciate @Jan's wrapper which works well for users who are aware it must be used, however, it doesn't prevent an unaware user from programmatically changing a UI component property value without an appropriate set/callback method being executed. For example, let's say the app is controlling a device. If values of UI component properties in the app are changed programmatically, no callback is executed to update the device. As a result, the device now has different settings than what is displayed in the app. This would not be an issue if SetObservable or SetAccess could be changed but to my knolwedge, that is not possible.
Jan
2021년 11월 11일
Of course poking values into the GUI objects instead of using the code as intented is always a method to confuse a program seriously. Users which use "hacking tools" to manipulate the GUI cannot expect it to work as expected.
shakedpa
2022년 10월 7일
@Jan I discovered this issue today, so I honestly ask what is the "intended" way to solve my needs:
I have a set of multiple toggle switches, they represent a state of the system (the fact that they are switches and not something else doesn't really matter, but I do need an actual GUI component and not some hidden state variable, because the users are expected to use some of the switches).
Because I don't want the users to have to set the full state every time, I added a "load settings" button, which loads a .mat file with a system-state variable, and assigns the correct values to all the switches.
Now, when the load button's callbak function set the correct values to the system-state switches, this doesn't fire their corresponding value-changed-callback-functions. I undrstand your comment that this is not the intended way to write this type of code, so I ask - how should I do it differently? (Instead of using one of the bypasses suggested here)
Specifically, how can I interact with multiple GUI components with one action, while still preserving their individual functionality?
Walter Roberson
2022년 10월 8일
If you are not willing to use the "work-around" of calling the callback function directly, then there are two possibilities I can think of:
- Write the code so that there are no callbacks for the toggle switches, that they do not trigger action at the time their state is changed, and instead have your "Go" push-button read the state of the switches and take appropriate actions; Or
- Construct the button state as properties with "SetObservable" attribute, and instead of having callbacks for the buttons, set up PostSet event listeners for them. Then when you load in new values for them, the listeners for them should fire. (I am not completely clear on the details... I would not currently rule out the possibility that you might need callbacks that convert the actions into setting the appropriate properties; that is, I am not certain that you can SetObservable a property within a graphics object.)
Walter Roberson
2022년 10월 8일
"however, it doesn't prevent an unaware user from programmatically changing a UI component property value without an appropriate set/callback method being executed"
A "user" who has access to **programmatically* change the ui component property values is a developer, so you are effectively asking how one developer can prevent a different developer from taking particular actions with the class that the second developer has source-code-modification access to.
If you want to divide an application into two parts, one modifiable by original developers and the second modifiable by less knowledgeable secondary developers, then put access restrictions on properties so that the secondary developers have to go through an interface to set the properties and the interface ensures that the necessary steps are taken to ensure consistency.
shakedpa
2022년 10월 10일
The original suggestion by Jan works fine, so that's ok for me. I felt there was a "more correct" way of doing it, but if there isn't anything obvious - nevermind.
Alexander Cranney
2021년 11월 15일
편집: Alexander Cranney
2021년 11월 15일
Another way to get the behavior you want is (mis)use a test case. Test cases have a number of methods for modifying GUI values in ways that mimic having a user manipulate the values, which fires all of the ChangedFcns. In this case, you can use the "type" method:
u = uieditfield();
u.ValueChangedFcn = @(s,e)disp(e);
fakeTestCase = matlab.uitest.TestCase.forInteractiveUse;
fakeTestCase.type(u,'2')
댓글 수: 1
Alexander Cranney
2021년 11월 15일
Ah, looks like you can do it in a single line without instantiating "fakeTestCase":
matlab.uitest.TestCase.forInteractiveUse.type(u,'2');
카테고리
도움말 센터 및 File Exchange에서 Develop Apps Programmatically에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!