Bonjour,
J'avais aussi essayé, ça ne fonctionnait pas (exactement le même comportement).
Je mets en résolu. Je posterai de nouvelles versions au fur et à mesure. Voici la première version, fonctionnelle avec l'aide disponible (help uiindexer) :
uiindexer.m
Un fichier d'exemple d'implémentation dans un programme simple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 function this = uiindexer(varargin) % UIINDEXER trace une serie de points et permets de recuperer l'index du % point sur lequel on clique, en temps reel % % Prend une serie de couples "propriete, valeur" en entree % A = uiindexer(prop1, val1, prop2, val2, ...) % Aucun ordre n'est necessaire pour la specification de ces couples. % % Proprietes disponibles : % % 'figure' : handle de la figure * % 'axes' : handle de l'axe (le parent de l'axe doit etre la figure) * % 'data' : les donnees traitees, si possible sur une seule ligne ou une % seule colonne % 'callback' : handle de la fonction a executer lorsqu'on change de point % selectionne avec la souris sur le graphique % 'texte' : handle de la fonction a executer qui doit retourner le % texte a afficher. Exemple (si le uiindexer s'appelle A) : % function txt = aTexte() % txt = {['Reel : ', num2str(A.x())], ... % ['Imag : ', num2str(A.y())], ... % ['Index : ', num2str(A.index())]}; % end % % * si aucune figure n'est specifiee, ou que l'axe n'est pas dans la % figure specifiee, alors une nouvelle figure est cree % % Accesseurs disponibles : % % A.figure() : handle de la figure % A.axes() : handle de l'axe % A.data() : donnees affichees % A.index() : index courant % A.x() : abscisse du point courant % A.y() : ordonnee du point courant % % Methodes disponibles : % % A.callback(@aCallback) : change le callback % A.texte(@aTexte) : change le texte a afficher dans la bulle % % Utilisation immediate dans le Command Window % -------------------------------------------- % % A = uiindexer % % % Cliquer sur un point de la figure, et afficher l'index courant avec : % % A.index() % % Exemple simple a enregistrer dans test.m et a executer % ------------------------------------------------------ % % function test % A = uiindexer('data', [-5-5*i -4+4*i -3-3*i -2+2*i -1-i 0 1+i 2-2*i 3+3*i 4-4*i 5+5*i], 'callback', @monCallback); % % A.texte(@aTexte) % % function txt = aTexte % txt = {['Abscisse : ', num2str(A.x())], ... % ['Ordonnee : ', num2str(A.y())], ... % ['Index : ', num2str(A.index())]}; % end % % function monCallback % b = A.data(); % disp( [ 'A(' , num2str(A.index()) , ') = ' , num2str(b(A.index())) ] ); % end % end % MAJ 2012-02-09 %% VARIABLES INTERNES data = []; % donnees a afficher index = 0; % index courant old_index = 0; % ancien index (limite les maj) f = []; % figure handle a = []; % axe handle callback = []; % callback handle texte = []; % texte a afficher handle x = 0; % abscisse courante y = 0; % ordonnee courante pos = 0; % position courante (x,y) txt = 0; % texte a afficher %% ACCESSEURS ET METHODES this = struct(... 'figure', @getFigure, ... 'axes', @getAxes, ... 'data', @getData, ... 'index', @getIndex, ... 'x', @getX, ... 'y', @getY, ... 'callback', @setCallback, ... 'texte', @setTexte); %% CONSTRUCTEURS if mod(nargin, 2) == 1 error('Mauvais format en entree : admet uniquement des couples (propriete, valeur)... tapez "help uiindexer" pour de plus amples informations.') else inputs = varargin; while length(inputs) >= 2 prop = inputs{1}; val = inputs{2}; inputs = inputs(3:end); switch lower(prop) case 'figure' f = val; case 'axes' a = val; case 'data' data = val; case 'index' disp('??? Warning ==> impossible to set "index" property') case 'callback' callback = val; case 'texte' texte = val; otherwise error(['The property "' num2str(prop) '" is not supported.']) end end if isempty(data) data = [-2-2*i 2+2*i -1+i 1+i 1-i -1-i]; end if isempty(index) index = 3; end if isempty(f) f = figure; end if isempty(a) a = axes('parent', f); elseif get(a, 'parent') ~= f a = axes('parent', f) end if isempty(callback) callback = 0; end % Configuration du curseur dcm_obj = datacursormode(f); set(dcm_obj, 'enable', 'on', ... 'snaptodatavertex', 'on', ... 'displaystyle', 'datatip', ... 'UpdateFcn', @updateIndex); % Affichage plot(a, data, 'x'); end %% ACCESSEURS function out = getFigure() out = f; end function out = getAxes() out = a; end function out = getData() out = data; end function out = getIndex() out = index; end function out = getX() out = x; end function out = getY() out = y; end %% METHODES function setCallback(in) callback = in; end function setTexte(in) texte = in; end %% CONFIGURATION DU CALLBACK function txt = updateIndex(empt, event_obj) index = get(event_obj, 'DataIndex'); if old_index ~= index pos = get(event_obj, 'Position'); x = pos(1); y = pos(2); old_index = index; callback(); end if isempty(texte) txt = {['Reel : ', num2str(pos(1))], ... ['Imag : ', num2str(pos(2))], ... ['Index : ', num2str(index)]}; else txt = texte(); end end end
Si certaine personnes sont intéressées par ce code, et seraient intéressées d'avoir de nouvelles fonctionnalités, je les invite à les demander ici. En fonction de la difficulté, de l'intérêt que cela apporte pour mon équipe, et du temps que cela prend pour le coder, je le ferai peut-être et le proposerai donc dans une nouvelle version. Si d'autres personnes veulent proposer une nouvelle version, je les invite à le faire également.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 function test % Pour plus d'information : % % help uiindexer % MAJ 2012-02-09 A = uiindexer('data', [-5-5*i -4+4*i -3-3*i -2+2*i -1-i 0 1+i 2-2*i 3+3*i 4-4*i 5+5*i], 'callback', @monCallback); A.texte(@aTexte) function txt = aTexte txt = {['Abscisse : ', num2str(A.x())], ... ['Ordonnee : ', num2str(A.y())], ... ['Index : ', num2str(A.index())]}; end function monCallback b = A.data(); disp( [ 'A(' , num2str(A.index()) , ') = ' , num2str(b(A.index())) ] ); end end
Futures fonctionnalités envisagées :
- configuration du datacursormode
- le faire fonctionner sur des plot différents, avec possibilité de choisir le type de plot sur lequel on veut dessiner (logarithmique par exemple, ou bien un bode "personnalisé"... j'envisage d'implanter un nouveau plot type "bode" mais qui laisse l'accès à la courbe de gain, et permet d'afficher / de mettre en valeur des caractéristiques remarquables comme la pulsation propre, les marges etc... - tout ceci via des options)
Cordialement,
ps: j'ai un petit bug à la con... lorsque je fais "help uiindexer", la première ligne de l'aide de "uiindexer.m" s'affiche puis la première ligne de l'aide de "test.m" s'affiche puis toute l'aide de "uiindexer.m" s'affiche enfin (y compris la première ligne qu'on voit donc affichée deux fois au final...). Un peu chelou cette histoire : vous avez le même problème ou pas ?
[EDIT] : en réalité, j'avais mis mes fichiers dans un répertoire portant le même nom que ma fonction... et lorsqu'on tape "help quelquechose", matlab cherche d'abord un dossier portant le nom "quelquechose"... s'il en trouve un, il cite les premières lignes d'aide de chaque fichier contenu dans "/quelquechose/". Ensuite, quoi qu'il en soit, il cite l'aide du fichier "quelquechose.m" s'il en trouve un. D'où mon "bug" qui n'en est pas un en fait, c'est juste que l'aide matlab ne le dit pas. D'ailleurs c'est bon à savoir, si on mets plusieurs fichiers "*.m" dans un répertoire, et qu'on tape help "nomdurépertoire", on obtient la première ligne d'aide de chaque fichier. D'ailleurs, c'est cette ligne qui est affichée dans la colonne "Description" en face de chaque fichier dans l'explorateur "Current Directory". Donc : problème entièrement résolu
Enjoy!
Bonjour,
Voici une nouvelle version (légères optimisations à droite à gauche).
Je ne la modifierai pas avant un bout de temps je pense. Entièrement libre. J'invite qui le veut bien de l'améliorer et/ou d'y apporter de nouvelles fonctionnalités et de poster sa version mise à jour ici.
uiindexer.m
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 function this = uiindexer(varargin) % UIINDEXER trace une serie de points et permets de recuperer l'index du % point sur lequel on clique, en temps reel % % Prend une serie de couples "propriete, valeur" en entree % .----------------------------------------------. % | A = uiindexer(prop1, val1, prop2, val2, ...) | % '----------------------------------------------' % Aucun ordre n'est necessaire pour la specification de ces couples. % % Proprietes (prop1, prop2, ...) disponibles avec valeurs a associer : % % 'figure' : handle de la figure * % 'axes' : handle de l'axe (le parent de l'axe doit etre la figure) * % 'data' : les donnees traitees, si possible sur une seule ligne ou une % seule colonne % 'callback' : handle de la fonction a executer lorsqu'on change de point % selectionne avec la souris sur le graphique % 'texte' : handle de la fonction a executer qui doit retourner le % texte a afficher. Exemple (si le uiindexer s'appelle A) : % function txt = aTexte() % txt = {['Reel : ', num2str(A.x())], ... % ['Imag : ', num2str(A.y())], ... % ['Index : ', num2str(A.index())]}; % end % % * si aucune figure n'est specifiee, ou que l'axe n'est pas dans la % figure specifiee, alors une nouvelle figure est cree % % Accesseurs disponibles : % % A.figure() : handle de la figure % A.axes() : handle de l'axe % A.data() : donnees affichees % A.index() : index courant % A.x() : abscisse du point courant % A.y() : ordonnee du point courant % % Methodes disponibles : % % A.callback(@aCallback) : change la propriete 'callback' % A.texte(@aTexte) : change la propriete 'texte' % % Utilisation immediate dans le Command Window % -------------------------------------------- % % A = uiindexer % % % Cliquer sur un point de la figure, et afficher l'index courant avec : % % A.index() % % Exemple simple a enregistrer dans test.m et a executer % ------------------------------------------------------ % % function test % A = uiindexer('data', [-5-5*i -4+4*i -3-3*i -2+2*i -1-i 0 1+i 2-2*i 3+3*i 4-4*i 5+5*i], 'callback', @monCallback); % % A.texte(@aTexte) % % function txt = aTexte % txt = {['Abscisse : ', num2str(A.x())], ... % ['Ordonnee : ', num2str(A.y())], ... % ['Index : ', num2str(A.index())]}; % end % % function monCallback % b = A.data(); % disp( [ 'A(' , num2str(A.index()) , ') = ' , num2str(b(A.index())) ] ); % end % end % MAJ 2012-02-16 %% VARIABLES PRIVEES data = []; % donnees a afficher index = 0; % index courant old_index = 0; % ancien index (limite les maj) f = []; % figure handle a = []; % axe handle callback = []; % callback handle texte = []; % texte a afficher handle x = 0; % abscisse courante y = 0; % ordonnee courante pos = 0; % position courante (x,y) txt = 0; % texte a afficher %% LISTE ACCESSEURS ET METHODES this = struct(... 'figure', @getFigure, ... 'axes', @getAxes, ... 'data', @getData, ... 'index', @getIndex, ... 'x', @getX, ... 'y', @getY, ... 'callback', @setCallback, ... 'texte', @setTexte); %% CONSTRUCTEUR if mod(nargin, 2) == 1 error('Mauvais format en entree : admet uniquement des couples (propriete, valeur)... tapez "help uiindexer" pour de plus amples informations.') else inputs = varargin; while length(inputs) >= 2 prop = inputs{1}; val = inputs{2}; inputs = inputs(3:end); switch lower(prop) case 'figure' f = val; case 'axes' a = val; case 'data' data = val; case 'index' disp('??? Warning ==> impossible to set "index" property') case 'callback' callback = val; case 'texte' texte = val; otherwise error(['The property "' num2str(prop) '" is not supported.']) end end if isempty(data) data = [-2-2*i 2+2*i -1+i 1+i 1-i -1-i]; end if isempty(index) index = 3; end if isempty(f) f = figure; end if isempty(a) a = axes('parent', f); plot(a, data, 'x'); elseif get(a, 'parent') ~= f a = axes('parent', f) plot(a, data, 'x'); end if isempty(callback) callback = 0; end % Configuration du curseur dcm_obj = datacursormode(f); set(dcm_obj, 'enable', 'on', ... 'snaptodatavertex', 'on', ... 'displaystyle', 'datatip', ... 'UpdateFcn', @updateIndex); end %% ACCESSEURS function out = getFigure() out = f; end function out = getAxes() out = a; end function out = getData() out = data; end function out = getIndex() out = index; end function out = getX() out = x; end function out = getY() out = y; end %% METHODES function setCallback(in) callback = in; end function setTexte(in) texte = in; end %% CONFIGURATION DU CALLBACK function txt = updateIndex(empt, event_obj) index = get(event_obj, 'DataIndex'); if old_index ~= index pos = get(event_obj, 'Position'); x = pos(1); y = pos(2); old_index = index; callback(); end if isempty(texte) txt = {['Reel : ', num2str(pos(1))], ... ['Imag : ', num2str(pos(2))], ... ['Index : ', num2str(index)]}; else txt = texte(); end end end
test.m
Cordialement,
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 % Pour plus d'information : help uiindexer function test % MAJ 2012-02-16 f = figure; ax = axes('parent', f); A = uiindexer('figure', f, 'axes', ax, 'data', [-5-5*i -4+4*i -3-3*i -2+2*i -1-i 0 1+i 2-2*i 3+3*i 4-4*i 5+5*i], 'callback', @monCallback); A.texte(@aTexte) plot(ax, [-5-5*i -4+4*i -3-3*i -2+2*i -1-i 0 1+i 2-2*i 3+3*i 4-4*i 5+5*i], 'x'); function txt = aTexte txt = {['Abscisse : ', num2str(A.x())], ... ['Ordonnee : ', num2str(A.y())], ... ['Index : ', num2str(A.index())]}; end function monCallback b = A.data(); disp( [ 'A(' , num2str(A.index()) , ') = ' , num2str(b(A.index())) ] ); end end
Partager