How to assign a class method as a ClickedCallback?

5 vues (au cours des 30 derniers jours)
Dominik Mattioli
Dominik Mattioli le 8 Jan 2020
The class may change, but the method names are the same.
classdef BaseClass < handle
properties
p = []
end
methods
function h = get_save_handle( obj )
h = @obj.save;
end
end
end
classdef Class1 < BaseClass
properties
p1 = []
end
methods
function save( obj )
% ...
end
end
end
classdef Class2 < BaseClass
properties
p2 = []
end
methods
function save( obj )
% ...
end
end
end
I need to change the callback of a save button in my UI depending on the user's data, which will determine which class is used. So if I'm using class1, the ClickedCallback of my save button needs to be class1.save(), etc. Here is how I assign the callback:
switch data_type
case 'Class1'
save_data = Class1();
case 'Class2'
save_data = Class2();
end
saveUIButton.set( 'ClickedCallback', { save_data.get_save_handle(), f }, 'UserData', save_data ) % 'f' is my figure.
But when I click the save button, the varargin{:} causes an error because the 'save' function arguments aren't compatible:
Error using Class1/save
Too many input arguments.
Error in BaseClass>@(varargin)obj.save(varargin{:}) (line 82)
h = @obj.save;
Error while evaluating PushTool ClickedCallback.
  3 commentaires
Mohammad Sami
Mohammad Sami le 14 Jan 2020
Most likely its because the button will pass itself and the event variables in the callback. So you need to add more variables to your save function. If you don't need them in your callback you can use ~ to replace the variable in the function signature.
function save( obj , ~ , ~)
Dominik Mattioli
Dominik Mattioli le 14 Jan 2020
Modifié(e) : Dominik Mattioli le 14 Jan 2020
These are valid workarounds, but not exactly what I was looking for.
I ended up just using polymorphism and not changing the callback function, which I suppose is the cleaner thing to do anyhow.
function save_button_callback( hObject, eventData, figureHandle )
data = hObject.get( 'UserData' );
data.save();
end
where, data is one of the derived classes. Just need to make sure that the save button's UserData is properly assigned.

Connectez-vous pour commenter.

Réponse acceptée

Steven Lord
Steven Lord le 14 Jan 2020
methods
function h = get_save_handle( obj )
h = @obj.save;
end
end
The name of the method is save.
methods
function h = get_save_handle( obj )
h = @save;
end
end
When that function handle gets executed, MATLAB will use the input arguments with which it was called to determine which function or method named save will be called. If the input isa Class1 the Class1 save method will be called. If it isa Class2 then Class2's save method will be called. If it's neither, the built-in save function will be called.
For example:
h = @plot; % No class information required to create h
% Sample data
g = graph(bucky);
x = 1:10;
figure
h(g) % the plot method for graph objects gets called
figure
h(x) % the built-in plot function (for double data) gets called
HOWEVER, I would be wary about overloading save for your objects, as it has kind of an important meaning already in MATLAB. If you're looking to customize what happens when you save your objects, you probably want to overload the saveobj and loadobj functions instead as described in this topic in the documentation. If your save method is intended to do something like writing the data to some other type of file rather than a MAT-file, I'd suggest a slightly longer and more descriptive name, something like saveTo<fileType>File (saveToTextFile or saveToTXTFile as an example.)

Plus de réponses (0)

Catégories

En savoir plus sur Data Type Identification dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by