2017-07-25 2 views
1

J'ai un code GUI Matlab qui vous permet de dessiner sur des axes et de transmettre les coordonnées à une constante dans Simulink. Pendant que le bouton de la souris est maintenu enfoncé, il faut dessiner sur les axes et envoyer les coordonnées et quand il ne l'est pas, il doit envoyer les coordonnées mais il ne doit pas dessiner. Voici le code: `La fonction matlab set_param ne fonctionne pas en boucle

function figure1_WindowButtonUpFcn(hObject, eventdata, handles) 
    % hObject handle to figure1 (see GCBO) 
    % eventdata reserved - to be defined in a future version of MATLAB 
    % handles structure with handles and user data (see GUIDATA) 
    global bool; 
    bool=false; 
    set(handles.figure1,'WindowButtonMotionFcn',@(hObject,eventdata)figure1_WindowButtonMotionFcn(hObject,eventdata,guidata(hObject))); 
    %set the WindownButtonMotionFcn back in order to make it work again 



function figure1_WindowButtonDownFcn(hObject, eventdata, handles) 
    set(handles.figure1,'WindowButtonMotionFcn',@empty); %change the windowbuttonmotionfcn in order not to let it work 
    global bool; 
    bool=true; 
    global lastX; 
    global lastY; 
    x=0; 
    while bool 
     coord=get(handles.axes4,'CurrentPoint'); 
     if coord(1)<0.003 
      coord(1)=0.003 
      x=0; 
     end 
     if coord(1)>1 
      coord(1)=1 
      x=0; 
     end 
     if coord(3)<0 
      coord(3)=0 
      x=0; 
     end 
     if coord(3)>0.95 
      coord(3)=0.95 
      x=0; 
     end 
     if x>1 
      arrayX=[lastX coord(1)]; 
      arrayY=[lastY coord(3)]; 
      line(arrayX,arrayY); 
      set_param('dosya_yukle_deneme/Constant','value',num2str(coord(1))); 
     end 
     x=x+1; 
     lastX=coord(1); 
     lastY=coord(3); 
     drawnow; 
    end 

function empty(~,~,~) 

% --- Executes on mouse motion over figure - except title and menu. 
function figure1_WindowButtonMotionFcn(hObject, eventdata, handles) 
    coord=get(handles.axes4,'CurrentPoint'); 
    set_param('dosya_yukle_deneme/Constant','value',num2str(coord(1))); 

Alors que le bouton de la souris enfoncé, il dessine les lignes, mais la fonction set_param ne fonctionne pas. Cependant, celui de la figure1_WindowButtonMotionFcn fonctionne plutôt bien en cas de besoin. Il semble que le problème est la boucle while. Toute aide serait appréciée.

Répondre

1

J'ai résolu le problème! J'ai donc découvert que le code fonctionnait depuis le début. J'avais connecté la constante à un affichage, tandis que la figure1_WindowButtonMotionFcn fonctionnait, elle affichait la valeur mais pas pendant que l'autre fonctionnait. Il semble que ce soit un bug dans MATLAB UI; l'affichage ne se renouvelle pas lorsqu'un bouton de la souris est détecté.

+2

Ce n'est pas un bug; c'est parce que la boucle while empêche le rappel de revenir. L'interface graphique de Matlab est à un seul thread, donc si un callback ne revient pas, alors l'interface graphique est bloquée et ne se met pas à jour correctement - voir la réponse – Tom

+0

@Tom eh bien, cela fonctionne réellement. mais au début, je ne m'attendais pas à ce que ça marche: D –

3

Vous ne pouvez pas exécuter votre boucle while au sein du rappel figure1_WindowButtonDownFcn car l'interface graphique de Matlab est monothread. Cela signifie que la boucle while bloque l'interface graphique de Matlab et empêche les choses de se mettre à jour correctement. Vous devez laisser revenir le rappel pour que Matlab puisse mettre à jour l'interface graphique. C'est une règle générale pour les rappels GUI dans Matlab; tout ce que vous faites dans le rappel bloquera l'interface graphique.

En fait vous n'avez pas du tout besoin d'une boucle while car WindowButtonMotionFcn va rappeler à chaque fois que le curseur change. Vous mettez le code à l'intérieur de la boucle dans le rappel figure1_WindowButtonMotionFcn. Vous aurez également besoin d'un drapeau global supplémentaire indiquant si le bouton est enfoncé ou non, mais c'est facile à créer. figure1_WindowButtonDownFcn devrait mettre le drapeau vers le bas, et figure1_WindowButtonUpFcn réinitialise le drapeau de bouton vers le bas. Ensuite, figure1_WindowButtonMotionFcn vérifie si le drapeau de bouton bas est réglé, et si c'est le cas, alors il exécute le code dans votre boucle while.

+1

+1. J'ajouterais aussi que si un _really_ avait besoin d'un vrai comportement asynchrone (c'est-à-dire multi-thread), on pourrait le faire en utilisant 'batch'. Mais, d'accord, ce n'est pas nécessaire ici. –

+0

merci pour la suggestion. mais ça marche très bien en fait et je n'ai pas vraiment besoin de meilleures performances etc. Je vais garder cela à l'esprit la prochaine fois que je devrai faire quelque chose comme ça. –