IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Interfaces Graphiques Discussion :

[datacursormode] Bloquer la vue d'un plot3, puis récupérer les coordonnées dans le programme


Sujet :

Interfaces Graphiques

  1. #1
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut [datacursormode] Bloquer la vue d'un plot3, puis récupérer les coordonnées dans le programme
    Bonjour,

    Cette discussion fait suite à celle-ci à titre d'information.

    Je souhaite afficher une série de points 3D dans un graphique 3D, mais bloquer la vue selon une direction, de telle sorte que l'utilisateur ne puisse pas tourner le graphique avec les options disponibles. Cela est-il faisable ?

    Par exemple, le code suivant affiche les pôles d'un système dans un graphique 3D (sur 'x' la partie réelle, sur 'y' la partie imaginaire et sur 'z' l'indice) et affiche la vue dans une certaine direction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    sys=tf([1], [1 2 3 4 5]); % ma fonction de transfert
    mesPoles=pole(sys);       % mes poles
    [m,n]=size(mesPoles);     % le nombre de poles dans m
    x=real(mesPoles);         % partie réelle des poles
    y=imag(mesPoles);         % partie imaginaire des poles
    z(m)=0;                   % indice de repérage des poles
    for k=1:1:m
        z(k) = k;
    end
     
    plot3(x,y,z,'x');         % mon graphique avec des croix pour chaque point
    view([0 0 1])             % vue de dessus
    Je voudrais donc déjà, en premier lieu, bloquer la vue. (tourner la vue est l'une des options disponibles au dessus du graphique).

    Mon objectif final est de récupérer les données (d'un point de vue programmation) qui ont permis de tracer le pôle sur lequel l'utilisateur va cliquer : pas seulement les valeurs 'x' & 'y', mais également l'indice 'z' qui me permet de les repérer dans "mesPoles". Je crois que j'ai déjà une piste avec "datacursormode"... j'ai donc déjà ma petite idée pour ce problème, mais pas pour le premier qui consiste à bloquer la vue. (A moins que quelqu'un sache directement comment récupérer l'indice des points tracés dans une vue 2D)

    Je vous remercie par avance pour toute aide.

    Cordialement,

    [EDIT] Après recherches un peu plus approfondies, j'ai trouvé comment récupérer l'indice du point sélectionné. Je l'ai appliqué sur un graphique 2D et ça marche bien (du moins ça l'affiche dans la console en temps réel). Exemple :

    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
    function testPoles
    sys = tf([1], [1 2 3 4 5];
    mesPoles = poles(sys);
     
    f=figure(1);
    plot(mesPoles, 'x')
     
    dcm_obj=datacursormode(f);
    set(dcm_obj, 'enable', 'on', ...             % activation du curseur
        'snaptodatavertex', 'on', ...            % le curseur s'aligne sur les points donnés uniqumeent
        'displaystyle', 'datatip', ...           % mode d'affichage (window ou datatip)
        'UpdateFcn', @myupdatefcn);
     
        function [txt, pos, indice] = my updatefcn(empt, event_obj)
            pos = get(event_obj, 'Position')     % récupère et affiche les coordonnées x et y du point
            indice = get(event_obj, 'DataIndex') % récupère et affiche l'indice du point
            txt = {['Re: ', num2str(pos(1))], ['Im: ', num2str(pos(2))], ['Index: ', num2str(indice)]};
        end
    end
    Maintenant, il faut encore que je sache comment je peux traiter ces données en temps réel dans mon programme pour faire ce que je veux, mais ça, c'est un autre problème.

    Il n'empêche que j'aimerai savoir s'il est possible de bloquer la vue 3D.

  2. #2
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 317
    Par défaut
    Citation Envoyé par tachmou Voir le message
    Je voudrais donc déjà, en premier lieu, bloquer la vue. (tourner la vue est l'une des options disponibles au dessus du graphique).
    Tu peux rendre le bouton concerné invisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    h = findall(0,'type','uitoggletool','tooltipstring','Rotate 3D');
    set(h,'visible','off');
    C'est bien entendu réversible

  3. #3
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    Merci encore pour ta réponse ! J'espère que cette réponse sera utile également à d'autres personnes et pas seulement à moi.

    Bon, maintenant, il faudrait qu'en fonction de la dernière valeur enregistrée dans "indice", je puisse mettre à jour tout le reste du programme qui dépend de mon fameux "indice"...

    Je suis formaté "Qt", donc si tu connais, en gros, j'aimerai créer une sorte de "signal" qui se déclenche dès que la valeur de mon "indice" change et qui puisse être lié à un "slot" dans lequel je pourrais faire toutes les modifications que je veux...
    ...mieux encore : j'aimerai que cette variable soit la sortie de ma fonction "dessinerEtRecupererIndice" (qui s'occupe donc de dessiner dans un "axe" les données d'entrée et de donner la possibilité à l'utilisateur de venir cliquer sur les points pour récupérer mon "indice" avant de le donner en sortie...) et que je puisse traiter dans mon programme principal le changement de valeur de cette sortie comme bon me semble.

    Voici un code de base :

    Programme principal
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    sys = tf([1], [1 2 3 4 5]);
    mesPoles = pole(sys);
    a = axes;
    [indice] = dessinerEtRecupererIndice(a, mesPoles);
     
    %% Code à rajouter pour traiter le changement de valeur d'indice
    %%
    Fonction récupérer indice
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function [indice] = dessinerEtRecupererIndice(a, mesPoles) %% <<= Rq. : j'ai mis indice en sortie
        plot(mesPoles, 'x') %% <<= ici j'aimerai aussi spécifier que je veux dessiner dans mon axe "a"... je ne sais pas comment faire non plus - certes ça le fait comme il faut si axe est le dernier élément créé... mais c'est magique ça aussi... et si jamais j'ai créé un autre axe ou figure entre temps ? et que je veux quand même l'afficher dans l'ancien axe ? 
        dcm_obj = datacursormode(a)
        set(dcm_obj, 'enable', 'on', ... 
            'snaptodatavertex', 'on', ... 
            'displaystyle', 'datatip', ...
            'UpdateFcn', @myupdatefcn);
    
        function [txt, indice] = myupdatefcn(empt, event_obj)  << j'ai mis "indice" en sortie
            pos = get(event_obj, 'Position');
            indice = get(event_obj, 'DataIndex');
            txt = {['Re: ', num2str(pos(1))], ['Im: ', num2str(pos(2))], ['Index: ', num2str(indice)]};
        end
    end
    (Codes non fonctionnels bien sûr)

    Je m'y prends très certainement très mal : n'hésitez pas à me l'indiquer ! J'aimerai juste un petit coup de pouce, je pense qu'il ne me manque pas grand chose pour que je puisse (enfin!) commencer à développer les outils dont j'ai besoin pour ma thèse...

    Cordialement,

    ps : Dis moi, j'en ai marre de poser des questions idiotes... il n'y aurait pas une doc un peu mieux foutu que l'officielle ? Comme tu as dû le remarquer, je cherche à faire des choses un minimum évoluées, et les infos intéressantes sont extrêmement éparpillées je trouve... en clair : je galère trop pour faire ce que j'ai envie de faire. Tu n'aurais pas un conseil "magique" à me donner à tout hasard ? D'ailleurs, comment tu as fait pour répondre à ma question ? Comment tu le sais ça, qu'il fallait chercher la propriété "tooltipstring" et que sa valeur est "Rotate 3D" ? C'est magique ça quand même...

    ps2 : délire perso parce que je craque... j'aimerai bien faire ctrl+c de ton cerveau partie matlab et ctrl+v dans le mien partie matlab... ok je sors

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function [txt, indice] = myupdatefcn(empt, event_obj)  << j'ai mis "indice" en sortie
    Étant contenu dans le fonctionnement interne du DATACURSORMODE, tu ne pourras pas récupérer tes indices de cette façon.
    Ce qui se rapproche le plus de ce que tu demandes sur les signaux/slots serait ceci qui est plus tourné Java. Mais il te serait plus simple d'utiliser le principe des fonctions imbriquées et de mettre ton traitement sur les indices directement dans la fonction myupdatefcn.

    Pour ce qui est du PLOT:
    Pour ce qui est du 'TooltipString', il faut juste savoir que les boutons présents sur la Toolbar des Figures sont des objets Uitoggletool, et que lors du survol de la souris, c'est le contenu de leur propriété 'TooltipString' qui est affiché. À partir de là, on recherche le handle de l'objet à partir de ces caractéristiques connues avec la fonction FINDALL.

  5. #5
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    Merci pour tes deux dernières réponses (le plot et le TooltipString, d'ailleurs j'ai envie de dire : "Tricheur!" mais merci pour le tuyau )

    Par contre, la première réponse ne me fait pas plaisir pour trois raisons :
    - Le lien que tu me files concernant les classes nécessite les dernières versions de Matlab... je ne l'avais pas spécifié ici, mais en fait je me trimballe avec la version 7R14 de 2005. J'ai d'ailleurs trouvé un autre moyen de créer des classes en utilisant justement les fonctions imbriquées.
    - Traiter les données dans la fonction myupdatefcn est juste "pas envisageable" : je compte utiliser ce type de fonctionnalité des dizaines voire des centaines de fois selon l'application/les système que je vais concevoir.
    - Je ne peux pas mettre mon "indice" en sortie... bon ok soit, mais il doit y avoir peut être moyen de faire une magouille avec les entrées non ? Et de jouer avec les "update" utilisé dans les gui ? Je m'explique...

    L'idée que j'ai mais que je n'arrive pas à concrétiser proprement, serait de créer (par exemple) un slider (ou autre...) qui ne serait pas visible sur la figure principale, et qui contient la valeur de mon indice. J'envoie le handle de ce slider en entrée de ma fonction "dessinerEtRecupererIndice", ainsi qu'en entrée de la fonction "myupdatefcn". Je mets donc à jour la valeur contenue dans mon slider... qui, en changeant, va appeler son "Callback" ! Et là, paf! ça fait des chokapik! (puisque dans le callback du slider qui m'intéresse je fais mon joyeux bordel... qui se trouvera donc comme je le voulais dans ma fonction principale !)

    Les applications sont multiples et j'envisage même de gérer différents types de plots etc... (j'en ai réellement besoin pour ma thèse si je veux répondre efficacement à une partie de mon sujet... ce n'est donc pas du superflu que je demande là)

    Galère galère...

    Merci à tous ceux qui ont eu le courage de me lire ! Ca paraît tordu, mais ça serait tellement utile et permettrait de faire tellement de choses !

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par tachmou Voir le message
    Merci pour tes deux dernières réponses (le plot et le TooltipString, d'ailleurs j'ai envie de dire : "Tricheur!" mais merci pour le tuyau )
    Bon d'accord l'expérience ça aide, mais l'histoire du plot c'est contenu dans la doc:
    Citation Envoyé par doc plot
    plot(axes_handle,...) plots using axes with the handle axes_handle instead of the current axes (gca).
    Le reste dans l'excellent tutoriel de Dut.

    Ensuite comme je te l'ai dit, le plus simple est d'utiliser les fonctions imbriquées, cependant je ne pensais pas à aux classes de l'autre discussion, mais simplement au passage de variable.
    Je ne vois pas en quoi
    Citation Envoyé par tachmou Voir le message
    Traiter les données dans la fonction myupdatefcn est juste "pas envisageable"
    Tu veux bien appeler ton Callback à chaque changement, non? Ou ai-je mal compris?
    Dernière modification par Invité ; 01/02/2012 à 21h07.

  7. #7
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    Oui, tu as bien compris ce point, mais... !

    En fait, j'ai l'intention d'utiliser cette fonction pour afficher des dizaines de graphiques différents, avec des données d'entrées différentes à chaque fois (c'est là que je trouve matlab utile d'ailleurs)... et donc, ce que je veux mettre dans mes callback... sera différent selon l'utilisation ! D'où ma question...

    Et puis, pour faire simple, l'indice que je vais récupérer avec ma souris, me permettra, à la fin, d'accéder à environ une centaine de variables (au très très bas mot...) - et ce - pour chacun des dizaines de graphiques différents ou je veux cette fonctionnalité : l'interprétation dépendra donc de l'étude que je suis en train de faire, et donc non pas du pauvre graphique que je viens d'afficher. Après tu me diras : tu es obligé de passer par des graphiques ?

    Non, mais ça aide à la compréhension, et quand tu étudies un système MIMO (linéarisé pour l'étude N°0002134, ce qui est déjà "censé" simplifier le travail), les pôles du système entier sont affichés sur le même graphique... si je veux savoir à quelle entrée et à quelle sortie ils sont liés, avec la fonction "bodeplot" je suis mal barré

    [En gros, pour faire schématique, imagine que je veuille faire un gui assez conséquent (je sais, matlab n'est pas prévu pour ça, il n'est prévu que pour faire des applications concrètes rapides, mais ça c'est un autre débat)... ce gui doit pouvoir proposer des outils de toutes sortes... pour structurer le tout et me simplifier la vie, je vais utiliser la POO de l'autre discussion (déjà appliqué en partie comme je l'ai dit, et c'est génial - merci encore d'ailleurs) et afficher des graphiques : seulement, j'ai environ une dizaine de graphiques différents à afficher, et je veux que chacun d'entre eux ai cette fonctionnalité qui me semble quand même assez basique : je suis fortement surpris que matlab ne propose pas dans sa magnifique doc une solution toute faite pour ça... comme ce n'est pas le cas, je m'attèle à cette tâche, j'en fait une classe ou une fonction qu'il faudra utiliser d'une certaine manière, et je l'utiliserai pour chacun des graphiques que j'aurai besoin d'afficher (je n'ai pas que des pôles à afficher, j'ai des courbes temporelles, des bodes "faits à la main" - pareil, j'ai fait mon propre bode et j'y ai rajouté des fonctionnalités de "base" que matlab ne propose pas sur ses bodes - et d'autres graphiques issus de la normes, et peut être encore d'autres graphiques dont je n'ai même pas idée aujourd'hui... donc je voudrai m'éviter de me compliquer la tâche à devoir à chaque fois recoder la même chose, d'autant que vu la taille du programme que je dois faire, je me vois mal tout mettre dans le même fichier pour travailler sur le même workspace...]

    Merci pour ton liens, je l'avais déjà épluché et ça m'avait bien aidé d'ailleurs, je les ai même imprimés en partie (en les résumant sur 3 pages) et affichés sur le mur juste en face de moi, je ne peux pas les louper ^^.

    Cordialement,

    ps: et pour répondre à une question qu'on m'a déjà posé : pourquoi je ne programme pas en C++ avec Qt directement ? Pour trois raisons : 1) j'ai envie de maîtriser matlab 2) c'est le langage utilisé par mes encadrants 3) matlab propose pleins d'outils qui m'intéressent vraiment et permet de travailler "en live" si on veut faire des tests, et je n'ai pas envie de refaire une grosse partie de ce qui est déjà très bien fait sur matlab (rapidité des calculs en plus...)

    ps2: la tâche paraît grosse... elle ne l'est pas tant que ça, il "suffit" de s'atteler à la tâche méthodiquement... et j'ai trois ans pour réaliser ma thèse, et on m'accorde quelques mois pour développer mes outils d'étude. Donc c'est faisable. Et puis si on ne se donne pas de challenge, c'est pas marrant !

    [EDIT] : Quelqu'un d'autre a fait quelque chose de similaire et passe par un "handle global"... moche, mais si c'est la seule solution, je l'utiliserai. Je vais essayer de coder ça. (par contre il a eu des bugs, je vais voir tout ça)

    [EDIT 2] : Aha! je pense que je tiens le bon bout avec evalin :
    evalin(ws, expression) executes expression, a string containing any valid MATLAB expression, in the context of the workspace ws. ws can have a value of 'base' or 'caller' to denote the MATLAB base workspace or the workspace of the caller function.
    Niark niak...

  8. #8
    Invité
    Invité(e)
    Par défaut
    Je ne vois toujours pas en quoi cela est un problème
    Je te propose un exemple simple, qui je l'espère t'aidera:
    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
    function exemple
     
    figs(1) = figure('Units','Normalized',...
        'Position',[0.5 0.5 0.4 0.4]);
    figs(2) = figure('Units','Normalized',...
        'Position',[0.5 0   0.4 0.4]);
    figs(3) = figure('Units','Normalized',...
        'Position',[0   0   0.4 0.4]);
    figs(4) = figure('Units','Normalized',...
        'Position',[0   0.5 0.4 0.4]);
     
    axs(1) = axes('Parent',figs(1),...
        'NextPLot','replaceChildren',...
        'XLim',[0 10],...
        'YLim',[0 10]); hps(1) = plot(axs(1),NaN,NaN);
    axs(2) = axes('Parent',figs(2),...
        'NextPLot','replaceChildren',...
        'XLim',[0 10],...
        'YLim',[0 10]); hps(2) = plot(axs(2),NaN,NaN);
    axs(3) = axes('Parent',figs(3),...
        'NextPLot','replaceChildren',...
        'XLim',[0 10],...
        'YLim',[0 10]); hps(3) = plot(axs(3),NaN,NaN);
    axs(4) = axes('Parent',figs(4),...
        'NextPLot','replaceChildren',...
        'XLim',[0 10],...
        'YLim',[0 10]); 
     
    donnees = 1:10;
    dessinerEtRecupererIndice(axs(4), donnees)
    indice = [];
    figure(figs(4))
     
        function dessinerEtRecupererIndice(a, mesPoles) %% <<= Rq. : j'ai mis indice en sortie
            plot(a,mesPoles, 'x') %% <<= ici j'aimerai aussi spécifier que je veux dessiner dans mon axe "a"... je ne sais pas comment faire non plus - certes ça le fait comme il faut si axe est le dernier élément créé... mais c'est magique ça aussi... et si jamais j'ai créé un autre axe ou figure entre temps ? et que je veux quand même l'afficher dans l'ancien axe ?
            dcm_obj = datacursormode(get(a,'Parent'));
            set(dcm_obj, ...
                'enable', 'on', ...
                'snaptodatavertex', 'on', ...
                'displaystyle', 'datatip', ...
                'UpdateFcn', @myupdatefcn);
        end
        function [txt] = myupdatefcn(empt, event_obj)
            pos = get(event_obj, 'Position');
            indice = get(event_obj, 'DataIndex');
            txt = {['Re: ', num2str(pos(1))], ['Im: ', num2str(pos(2))], ['Index: ', num2str(indice)]};
            MajTraces
        end
        function MajTraces
            set(hps(1),'XData',[indice indice], 'YData',ylim)
            set(hps(2),'XData',xlim, 'YData',[indice indice])
            set(hps(3),'XData',[0 indice], 'YData', [0 indice])
        end
    end

  9. #9
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    Je te remercie beaucoup pour ton exemple, ça m'a éclairé sur certains autres points au passage, il est intéressant (sans ironie), mais...

    Imagine que je veuille, pour mon application 1, faire "MajTraces1", puis pour mon application tartenpion, faire "MajTracesTartenpion", etc... je suis obligé de recoder tout ce que tu as fait à chaque fois et faire les traitements nécessaires dans toutes ces sous fonctions... c'est lourd et long (pas pour une petite application, mais pour un gros bordel si)

    Moi j'imaginais plutôt coder une sorte de "boîte noire" que tu viendrais piocher parmis toutes les autres "boîtes noires" qui prend
    En entrée :
    - le handle de ton graphique (et peut-être d'autres options)
    En "sortie" :
    - l'index qui déclenche un callback à l'extérieur de sa propre fonction

    Lorsque l'index change, ça déclenche un callback d'un certain type dans le programme de l'utilisateur, et lorsqu'il est déclenché, l'utilisateur fait ce qu'il veut dans son propre callback.

    Je te rappelle que je suis thésard, et qui dit thésard dit gros gros gros fainéant : tout ce qui peut me simplifier la vie est bon à prendre (ou à développer dans mon cas).

    Mais j'y suis presque, je posterai ma "boîte noire" en question.

    Cordialement,

    ps : ah et sinon j'ai trouvé un slider un peu mieux foutu que l'officiel sur matlab central... (concerne l'autre discussion) il n'est pas temps réel mais bon, c'est le genre de "boîte noire" que je comptais développer aussi. C'est déjà fait : tant mieux !

  10. #10
    Invité
    Invité(e)
    Par défaut
    N'ayant pas une vue globale sur ce que tu veux faire, il est difficile de bien t'orienter... Je ne fais qu'en fonction de ce que tu me dis (et ce que je comprends).
    Après tu peux très bien te servir du principe de l'autre discussion et y rajouter les éléments de celle-ci.

  11. #11
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    Je me rends bien compte que je touche du doigt un point particulier. Avec le code suivant, tu devrais comprendre. L'intérêt, c'est qu'au final, grâce à ce "truc" que j'essaye de coder, eh bien l'utilisateur pourra l'utiliser en faisant par exemple :

    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
    function gui_numero_xxx
        % Création des variables
        sys = tf([1], [1 2 3 4 5]);
        mesPoles = poles(sys);
    
        % Mise en place du graphique
        f = figure(1)
        a = axes('parent', f);
        i = uicontrol('Style', 'indexFromClick', ...
            'DataIn', mesPoles, 'parent', a, 'Value', 0, ...
            'Callback', @indexFromClick_Callback); % cf EXPLICATION après le cadre
    
        function indexFromClick_Callback(src, evt)
            % Mise à jour de mon programme dès que le 'Value' de l'index 'i' change 
        end    
        
    end
    EXPLICATION
    Mon 'uicontrol' sera de type 'indexFromClick' (que je suis donc en train de créer, j'y arrive petit à petit, il faut que je règle quelques détails). Il a besoin des données à afficher 'DataIn' (ici mesPoles), du handle de l'axe où je veux les afficher (ici a), la valeur 'Value' par défaut (ici 0), et le nom du 'Callback' qui s’exécutera dès que la valeur de 'Value' changera (ici ma 'Value' sera la valeur de mon index...)

    Pour cela, je suis en train d'apprendre le fonctionnement des timer (je viens donc vérifier régulièrement la valeur de mon index : dès qu'elle change, je déclenche la fonction "Callback"). Et pour pouvoir implémenter cela à la sauce (merdique soit dit en passant - oui je sais, je me mets toute la communauté matlab à dos) matlab, et bien j'ai besoin d'apprendre à faire des fonctions qui puissent s'utiliser avec des "set" et des "get".

    Bon, ce ne sera peut-être pas un uicontrol, ce sera peut-être un autre truc au même niveau que "root" qui possèdera mon nom, mais ça c'est du détail .

    Cordialement,

    ps: vu à quel point je m'em***** pour faire cette fichu fonctionnalité, ce sera certainement la seule que je ferai, j'ai autre chose à faire après

    ps2: si quelqu'un se sent de faire ce boulot à ma place gratuitement, j'accepte... (utopie, utopie, quand tu nous tiens !)

  12. #12
    Invité
    Invité(e)
    Par défaut
    Alors une solution déjà mentionnée:
    Citation Envoyé par Winjerome Voir le message
    Ce qui se rapproche le plus de ce que tu demandes sur les signaux/slots serait ceci qui est plus tourné Java.
    Mais comme tu m'as dit:
    Citation Envoyé par tachmou Voir le message
    - Le lien que tu me files concernant les classes nécessite les dernières versions de Matlab... je ne l'avais pas spécifié ici, mais en fait je me trimballe avec la version 7R14 de 2005.
    Alors
    Citation Envoyé par Winjerome Voir le message
    Après tu peux très bien te servir du principe de l'autre discussion et y rajouter les éléments de celle-ci.
    Il n'y a pas grand chose à changer sur ce qui a déjà été fait. Juste la gestion des entrées/sortie de ta "classe"
    Allez au boulot

  13. #13
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    J'ai une première version simplifiée fonctionnelle, mais pas comme je le souhaite car :
    - j'utilise une variable globale alors que je voudrais pouvoir utiliser "get(a, 'index')" dans ma fonction "aCallback" (ce que je n'arrive pas à faire marcher)
    - les "set" ne fonctionnent pas comme prévu
    (je crois savoir d'où proviennent mes erreurs : j'ai utilisé des "nested functions" au lieu des functions classiques de matlab)

    Je la poste quand même... Arborescence générale :
    main/@uiindexer/uiindexer.m
    main/@uiindexer/set.m
    main/@uiindexer/get.m
    main/main.m

    main/@uiindexer/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
    % uiindexer
     
    function this = uiindexer(varargin)
        %% Definition de la structure de mon objet
        this = struct(...
            'data',                 [0],        ...
            'index',                0,          ...
            'callback',             0);
        global new_index;
        new_index = 0;
        old_index = 0;
     
        %% Constructeurs
        if nargin == 0 % par defaut
        end
        if nargin == 1 % de copie
            if (isa(varargin{1}, 'uiindexer'))
                this = varargin{1};
            else
                error('Wrong argument type')
            end
        else % quelconque
            property_argin = varargin(1:end);
            while (length(property_argin) >= 1)
                property = property_argin{1};
                value    = property_argin{2};
                property_argin = property_argin(3:end);
                switch lower(property)
                    case 'datain'
                        this.data = value
                    case 'callback'
                        this.callback = value;
                    otherwise
                        msg = sprintf('Propriete inconnue : "%s"', property);
                        error(msg);
                end
            end
        end
     
        this.figure = figure;
        this.axe = axes('parent', this.figure);
        plot(this.axe, this.data, 'x');
     
     
        % Curseur    
        dcm_obj = datacursormode(this.figure);
        set(dcm_obj, 'enable', 'on', ...
            'snaptodatavertex', 'on', ...
            'displaystyle', 'datatip', ...
            'UpdateFcn', @myupdatefcn);
        function [txt, truc] = myupdatefcn(empt, event_obj)
            pos = get(event_obj, 'Position');
            new_index = get(event_obj,'DataIndex');
            txt = {['Reel : ', num2str(pos(1))], ...
                ['Imag : ', num2str(pos(2))], ...
                ['Index:', num2str(new_index)]};
        end
     
        % Demarrage
        t = timer;
        set(t, 'executionMode', 'fixedRate');
        set(t, 'timerFcn', @createCallback);
        set(t, 'Period', 0.01);
        start(t);
        function createCallback(obj, evt)
            if old_index ~= new_index
                old_index = new_index;
                this = set(this, 'index', new_index);
                this.callback();
            end
        end
     
        %% Sortie en tant que "class" matlab
        this = class(this, 'uiindexer');
    end
    main/@uiindexer/set.m
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function a = set(a, propName, propValue)
        propName = lower(propName)
        switch propName
            case 'datain'
                a.data = propValue;
            case 'index'
                a.index = propValue;
            otherwise
                error([propName, ' Is not a valid uiindexer property'])
        end
    end
    main/@uiindexer/get.m
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function val = get(a, propName)
        propName = lower(propName)
        switch propName
            case 'datain'
                val = a.data;
            case 'index'
                val = a.index;
            otherwise
                error([propName, ' ...is not a valid uiindexer property'])
        end
    end
    main/main.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
    function main
        delete(timerfindall);
        global new_index;
        new_index = 0;
        data = [-5-5*i 5+5*i 3+i 0 -4+i -1-2*i -2-i];
        a = uiindexer('DataIn',  data, 'Callback', @aCallback)
        
        function aCallback % se déclenche dès qu'on clique sur un nouveau point du graphe OU BIEN dès qu'on "déplace" la sélection courante sur un nouveau point
            % Affichage de l'index :
            new_index 
    
            %%
            % ici, on a nos "data" et notre index "new_index"... l'utilisateur peut en faire ce qu'il veut, en temps réel !
            %%
    
        end
    end
    Il suffit d'exécuter le main pour faire un test rapide. Notez la simplicité d'utilisation...

    Cordialement,

  14. #14
    Expert confirmé
    Avatar de duf42
    Homme Profil pro
    Formateur en informatique
    Inscrit en
    Novembre 2007
    Messages
    3 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Formateur en informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 111
    Par défaut
    Bonjour,

    Je suis pas sûr que ce soit une bonne idée de nommer tes fonctions GET et SET: elles vont cacher les fonctions GET et SET de MATLAB ce qui peut entrainer des erreurs (c'est d'ailleurs le cas chez moi lorsque j'exécute ton MAIN).

    De plus, je ne comprends pas bien pourquoi tu déclares des variables globales, surtout que tu ne les utilises pas (pas comme des variables globales en tous cas).

    Duf

  15. #15
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bonjour,

    J'avais oublié de virer cette variable globale (que je n'utilise pas) du main. J'étais en train d'updater, désolé.

    Quelles erreurs tu as sur matlab ? J'utilise pourtant la méthode décrite par la doc officielle matlab (version R14SP3) pour définir set et get pour ses propres objets.

    Cordialement,

  16. #16
    Expert confirmé
    Avatar de duf42
    Homme Profil pro
    Formateur en informatique
    Inscrit en
    Novembre 2007
    Messages
    3 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Formateur en informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 111
    Par défaut
    Désolé j'ai été un peu trop vite, je n'avais pas mis les fichiers dans l'arborescence correcte

  17. #17
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    J'ai remis à jour (désolé) : en fait il y a bien besoin d'une global, mais sur new_index... T'en penses quoi ? De toutes façons, je revois tout ça demain, il se fait tard maintenant ^^

    j'ai aussi rajouté "delete(timerfindall)" (parce que mon code n'est pas propre, les timers sont laissés ouverts ) au cas où tu réexecute plusieurs fois.

  18. #18
    Invité
    Invité(e)
    Par défaut
    Un Timer... pourquoi pas. Moi j'aurais juste mis dans la fonction myupdatefcn un appel à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.Callback(new_indice)
    Qui aurait fait passer la valeur du nouvel indice, sans besoin d'un global.

    Pour les get/set à mettre en "interne" comme dans l'autre discussion (ma_fcn1 et ma_fcn2), ce qui donnerait quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    obj = uiindexer(...);
    obj.set(...)
    val = obj.get(...)

  19. #19
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    [EDIT : ce message est long et est à moitié useless, et je conseille de passer directement au suivant... je laisse celui-ci car si quelqu'un trouve une solution, je suis quand même preneur.)

    Bonjour,

    Je galère... vous allez comprendre pourquoi :

    Citation Envoyé par Winjerome Voir le message
    Un Timer... pourquoi pas. Moi j'aurais juste mis dans la fonction myupdatefcn un appel à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.Callback(new_indice)
    Qui aurait fait passer la valeur du nouvel indice, sans besoin d'un global.
    ==> Ce n'est pas possible : quand on est dans la fonction myupdateFcn, on n'a pas accès à notre objet (this est inaccessible). Il suffit de rajouter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    disp('DEBUT')
    this
    disp('FIN')
    pour le vérifier rapidement... (FIN devrait s'afficher à moment donné, mais ne le fait pas : il essaye d'accéder à "this", n'y arrive pas, mais n'affiche pas d'erreur, c'est le comportement de datacursormode qui ne l'a pas prévu).

    Citation Envoyé par Winjerome Voir le message
    Pour les get/set à mettre en "interne" comme dans l'autre discussion (ma_fcn1 et ma_fcn2), ce qui donnerait quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    obj = uiindexer(...);
    obj.set(...)
    val = obj.get(...)
    Je voudrais bien le faire, mais le souci, c'est que j'ai décidé de créer ma fonctionnalité à la "sauce matlab"... donc je transforme ma structure this en "classe" avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this = class(this, 'uiindexer');
    ce qui permet de faire fonctionner le tout à la sauce matlab, certes, mais ne permet donc plus d'accéder à des méthodes définies directement dans la structure. Si je n'arrive pas à faire fonctionner le tout à la sauce matlab, c'est ce que je ferais bien sûr.




    Bon, j'ai recodé le tout pour que ce soit encore plus propre qu'avant, en suivant les consignes de la doc à la lettre, et.... ça foire toujours, of course. Voici le code actuel (remplace entièrement le précédent) :

    ../@uiindexer/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
    function this = uiindexer(varargin)
    % UIINDEX
        global internal_uiindexer_index
        internal_uiindexer_old_index = 0;
        internal_uiindexer_index = 0;
        function_callback = 0;
        this = struct(...
            'data',             0, ...
            'index',            [], ...
            'figure',           [], ...
            'axe',              0, ...
            'callback',         0);
        if nargin == 1 %% Copy constructor
            if (isa(varargin{1}, 'uiindexer'))
                this = varargin{1};
            else
                error('Wrong argument type.')
            end
        elseif mod(nargin, 2) == 1
            error('Wrong inputs. Admits only pairs of (property,value)')
        else
            if nargin == 0 %% Default constructor
                this.data = [-2-2*i 2+2*i -1+i 1+i 1-i -1-i];
                this.index = 3;
                this.figure = figure;
                this.axe = axes('parent', this.figure);
            end
            inputs = varargin;
            while length(inputs) >= 2
                prop = inputs{1};
                val  = inputs{2};
                inputs = inputs(3:end);
                switch lower(prop)
                    case 'figure'
                        this.figure = val;
                    case 'axe'
                        this.axe = val;
                    case 'data'
                        this.data = val;
                    case 'index'
                        disp('??? Warning ==> impossible to set "index" property')
                        this.index = [];
                    case 'callback'
                        this.callback = val;
                        function_callback = val;
                    otherwise
                        error(['The property "' num2str(prop) '" is not supported.'])
                end
            end
            if isempty(this.figure)
                this.figure = figure;
                this.axe = axes('parent', this.figure);
            end
            dcm_obj = datacursormode(this.figure);
            set(dcm_obj, 'enable', 'on', ...
                'snaptodatavertex', 'on', ...
                'displaystyle', 'datatip', ...
                'UpdateFcn', @updateIndex); %%%%% <- ICI je fais appel à ma fonction (en suivant les consignes de datacursormode)
            plot(this.axe, this.data, 'x');
            this = class(this, 'uiindexer');
        end
    
    function txt = updateIndex(empt, event_obj)
        global internal_uiindexer_index
        pos = get(event_obj, 'Position');
        index = get(event_obj, 'DataIndex');
        if internal_uiindexer_index ~= index
            internal_uiindexer_index = index
            disp('MAJ "index"... ("FIN" doit apparaitre ci-dessous)')
            this = set(this, 'index', index);     %%%%%% <- ICI je voudrais mettre à jour mon index dans ma classe
            disp('FIN')                    %%%%%% <- FIN ! (mais ne marche pas pour l'instant à cause de la ligne précédente)
        end
        txt = {['Reel : ', num2str(pos(1))], ...
            ['Imag : ', num2str(pos(2))], ...
            ['Index :', num2str(index)]};
    ../@uiindexer/set.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
    function this = set(this, varargin)
    % SET Set uiindexer properties and return the updated object
    inputs = varargin
    while length(inputs) >=2
        prop = inputs{1};
        val = inputs{2};
        inputs = inputs(3:end);
        switch lower(prop)
            case 'figure'
                disp('Impossible to change figure: create new uiindexer for this pupose.')
            case 'axe'
                disp('Impossible to change axe: create new uiindexer for this pupose.')
            case 'index'
                this.index = val;
            case 'data'
                this.data = val;
                hold off
                this.index = [];
                plot(this.axe, this.data, 'x');
            otherwise
                error('Wrong arguments')
        end
    end
    ../@uiindexer/get.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
    function val = get(this, prop)
    % GET Get uiindexer properties from the specified object and return the
    % value
    switch lower(prop)
        case 'figure'
            val = this.figure;
        case 'axe'
            val = this.axe;
        case 'data'
            val = this.data;
        case 'index'
            if isempty(this.index)
                disp('Index undefined')
            elseif this.index == 0
                disp('Index undefined')
            end
            val = this.index;
        otherwise
            error(['"' prop '" is not a valid uiindexer property.'])
    end
    ../@uiindexer/display.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
    function display(this)
    % DISPLAY(uiindexer_obj) Display an uiindexer object
    disp(' ')
    disp(['Properties:']);
    disp('    data, index, figure*, axe*')
    disp('* GET only or initialize on construction')
    disp(' ');
     
    disp([inputname(1) ' = '])
    if (this.index == 0)
        disp(['    data:  ' num2str(this.data)])
        disp(['    index:  undefined'])
    elseif isempty(this.index)
        disp(['    data:  ' num2str(this.data)])
        disp(['    index:  undefined'])
    elseif this.index == 1
        disp(['    data:  ' ' [' num2str(this.data(1)) '] ' num2str(this.data(2:end))])
        disp(['    index: ' num2str(this.index)])
    elseif this.index == length(this.data)
        disp(['    data:  ' num2str(this.data(1:this.index-1)) ' [' num2str(this.data(this.index)) '] '])
        disp(['    index: ' num2str(this.index)])
    else
        disp(['    data:  ' num2str(this.data(1:this.index-1)) ' [' num2str(this.data(this.index)) '] ' num2str(this.data(this.index+1:end))])
        disp(['    index: ' num2str(this.index)])
    end
    disp(' ')
    Pour le tester :
    Vous pourrez remarquer mes commentaires à la fin du fichier uiindexer.m qui montre où est précisément mon problème. Lors de l’exécution, on constate bien que les lignes qui m'intéressent ne s’exécutent pas puisque "FIN" ne s'affiche pas (lors du clic sur un point du graphique). De plus, si vous faites un :
    dans la console après avoir cliqué sur un point de la courbe, l'index reste bloqué à sa valeur par défaut (j'ai mis 3 pour le constructeur par défaut).

    Cordialement,

    ps: vous pouvez vous amuser à modifier les données d'entrées comme bon vous semble avec set ou directement lors de la définition en faisant "a=uiindexer('data', donnee_perso)" (donnee_perso étant un tableau de données à afficher) ou à l'implémenter dans la figure et l'axe de votre choix, etc...

  20. #20
    Membre émérite
    Homme Profil pro
    Doctorant automatique
    Inscrit en
    Janvier 2012
    Messages
    446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant automatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 446
    Par défaut
    Bon,

    En appliquant la méthode "Pseudo POO", ça marche, c'est beau, c'est rapide et ça marche... ah oui, et ça marche aussi. Ai-je spécifié que ça marche ?

    Un seul fichier, pas de restriction sur le nom du répertoire :

    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
    function this = uiindexer(varargin)
    % UIINDEX
        %% VARIABLES
        data = [];
        index = [];
        f = [];
        a = [];
        callback = [];
        this = struct(...
            'data',             @getData, ...
            'index',            @getIndex, ...
            'figure',           @getFigure, ...
            'axe',              @getAxe, ...
            'callback',         @setCallback);
     
        %% CONSTRUCTEURS
        if mod(nargin, 2) == 1
            error('Wrong inputs. Admits only pairs of (property,value)')
        else
            if nargin == 0 %% Default constructor
            end
            inputs = varargin;
            while length(inputs) >= 2
                prop = inputs{1};
                val  = inputs{2};
                inputs = inputs(3:end);
                switch lower(prop)
                    case 'figure'
                        f = val;
                    case 'axe'
                        a = val;
                    case 'data'
                        data = val;
                    case 'index'
                        disp('??? Warning ==> impossible to set "index" property')
                        index = 0;
                    case 'callback'
                        callback = 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);
            end
            if isempty(callback)
                callback = 0;
            end
            dcm_obj = datacursormode(f);
            set(dcm_obj, 'enable', 'on', ...
                'snaptodatavertex', 'on', ...
                'displaystyle', 'datatip', ...
                'UpdateFcn', @updateIndex);
            plot(a, data, 'x');
        end
     
        function out = getIndex()
            out = index;
        end
     
        function setCallback(in)
            callback = in;
        end
     
        function txt = updateIndex(empt, event_obj)
            pos = get(event_obj, 'Position');
            index = get(event_obj, 'DataIndex');
            callback();
            txt = {['Reel : ', num2str(pos(1))], ...
                ['Imag : ', num2str(pos(2))], ...
                ['Index :', num2str(index)]};
        end
    end
    Utilisation :

    Puis cliquez sur le graphique...

    et récupérer l'index :

    Oh miracle, ça marche, c'est puissant, c'est rapide, c'est intuitif, c'est simple...

    Lors de la création, on peut spécifier la figure, l'axe et les données.

    Bon, je vais rester avec cette fonction... au pire, peut-être que je l'implémenterai dans une classe façon matlab pour ne pas dépayser les utilisateurs "classiques" de matlab (donc set, get etc...). J'essaye pour l'instant de mettre un maximum de fonctionnalités.

    Cordialement,

    ps je suis de retour vendredi, pas avant.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 2
    Dernier message: 01/07/2009, 08h54
  2. [MySQL] comment stocker puis recuper les images dans une base de donnée
    Par essono dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 22/11/2006, 23h07
  3. Réponses: 1
    Dernier message: 22/11/2006, 22h49
  4. Réponses: 1
    Dernier message: 02/11/2006, 10h40
  5. Réponses: 20
    Dernier message: 23/03/2006, 16h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo