Este exemplo mostra como criar uma interface gráfica para obter a distância entre pontos em uma figura. O principal neste exemplo é a interface e como trabalhar com os componentes, pois a distância entre os pontos pode ser obtida por diversas outras formas, podendo até mesmo ser automatizada.
Download dos arquivos (8.9 KB).
Para criar uma interface no MATLAB, basta chamar a função guide no prompt do MATLAB. Esta função trará a seguinte janela:
Neste exemplo, podemos ficar com a opção padrão (Blank GUI) e você também pode salvar a figura (interface) com a opção Save new figure as. Quando você salvar, o MATLAB criará automaticamente um arquivo *.m correspondente à sua interface e já adiciona a este arquivo um monte coisa necessária ao bom funcionamento da interface. Este arquivo conterá o código para as ações dos botões, controles de texto, menus e demais componentes existentes na interface. Clicando em OK, temos a nova interface:
Agora você já pode colocar os componentes na interface. Basta selecionar um componente na lista à esquerda e colocá-lo na interface com um clique. Todos os componentes suportam o recurso de arrastar e soltar e também têm alças de redimensionamento, que você já deve ter visto em algum outro programa. Para alterar cores, fonte e texto dos componentes, basta clicar duas vezes sobre ele, irá aparecer o editor de propriedades, onde você pode modificar facilmente as característica dos controles e da própria interface. Para o exemplo, eu usei uma interface assim (clique para ver maior):
Esta interface funcionará da seguinte forma: o usuário clica em “Abrir imgem” e escolhe uma figura, que será aberta no componente axes1; em seguida, ele especifica uma distância conhecida usando a caixa de texto abaixo do botão “Referência” e escolhe a unidade em que está a distância com o menu logo abaixo. Então ele clica no botão “Referência” e marca na figura onde está a distância conhecida. Depois basta escolher com quantos pontos ele quer trabalhar (na minha interface eu chamei de “Estações”), clica em “Marcar pontos” e marca os pontos na figura. Conforme ele marca os pontos as distâncias são calculadas e mostradas sobre a figura. Veja em funcionamento (note que no editor de propriedades eu coloquei a propriedade ToolBar da figura como figure para ter acesso às ferramentas de imagem durante a execução do programa) (clique para ver maior):
Para ver funcionando você pode clicar no triângulo verde do GUIDE ou apertar F5 no editor de códigos. Para chamar a interface futuramente, basta usar o nome que você deu a ela como se fosse uma função (e é isso que ela é), você pode chamá-la dentro de outros programas ou direto do promtp (ela deve estar acessível no path).
Para associar ações aos componententes, o MATLAB utiliza os chamados callbacks, que são apenas funções chamadas quando alguma coisa acontece. Veremos como funciona na prática: clicando com o botão direito sobre um componente, aparece um menu, neste menu há a opção View Callbacks que mostra todos os callbacks disponíveis para um componente e você ó precisa clicar em qual você quer editar e o MATLAB mostra onde digitar e, para alguns componentes, já trás algumas dicas. Veja o código que eu coloquei no callback do botão “Abrir imagem” (os comentários em inglês foram colocados automaticamente pelo MATLAB):
% --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) % hObject handle to pushbutton1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % mostra uma tela para que o usuário escolha um arquivo de imagem: [filename, canceled] = imgetfile; % se o usuário não tiver cancelado if ˜canceled % guarda o nome do arquivo handles.arquivo = filename; % abre a imagem handles.imagem = imread(filename); % seleciona o componente axes1 axes(handles.axes1); % exibe a figura imshow(handles.imagem); end % reseta a referência handles.px2min = NaN; % salva a variável handles guidata(hObject, handles);
Handles são números que identificam os componentes, eles ficam armazenados na variável handles. Essa variável é do tipo struct e é muito importante: é a única que está disponível para todos os callbacks, pois é salva com a função guidata. Veja que eu aproveitei ela para guardar o nome do arquivo e também a imagem.
Agora o callback do botão “Referência”:
% --- Executes on button press in pushbutton3. function pushbutton3_Callback(hObject, eventdata, handles) % hObject handle to pushbutton3 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % ativa o axes1 axes(handles.axes1); % mostra a imagem (isso reseta a imagem quando marcamos uma nova referência) imshow(handles.imagem); % pegamos qual a distância que o usuário que marcou % ("edtRef" é a propriedade "Tag" da caixa de texto) numRef = str2double(get(handles.edtRef, 'String')); % Vê se o usuário digitou um número válido, caso contrário % mostra uma mensagem e sai desse callback if isnan(numRef) || (numRef <= 0) % mostra a mensagem errordlg('Por favor, digite um número válido.', 'Erro'); % sai da função return; end % pede para o usuário marcar dois pontos ptos = ginput(2); % calcula a distância em pixels que o usuário marcou. % se você estudou vetores, sabe que distância entre pontos % pode ser obtida pela norma do vetor que tem % início num ponto e fim no outro, então basta chamar % a função norm com a diferença entre os pontos como % parâmetro. c = norm(ptos(1,:)-ptos(2,:)) / numRef; % converte a distância em pixels para milhas náuticas, levando % em consideração que o usuário pode ter marcado em qualquer % unidade disponível. % get(handles.popupmenu1, 'Value') retorna qual item o usuário escolheu switch get(handles.popupmenu1, 'Value') case 1 % minuto fator = c; case 2 % segundo fator = c / (1/60); case 3 % grau fator = c / 60; case 4 % quilometro fator = c / (1/(1852 * 1000)); case 5 % metro fator = c / (1/1852); end % guarda a referência handles.px2min = fator; guidata(hObject, handles);
Veja que continuamos usando os handles, agora para obter propriedades dos componentes usando a função get (para mudar propriedades via código, usa-se set).
Finalmente, o callback do botão “Marcar pontos”. Nesse eu vou usar a mesma técnica que autores famosos de livros técnicos usam quando têm preguiça: não vou comentar para estimular o raciocínio do leitor.
% --- Executes on button press in pushbutton2. function pushbutton2_Callback(hObject, eventdata, handles) % hObject handle to pushbutton2 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) if isnan(handles.px2min) errordlg('Marque a referência primeiro', 'Erro'); return; end numEst = str2double(get(handles.edtNumEst, 'String')); if ~isnan(numEst) && numEst > 1 axes(handles.axes1); pto = ginput(1); hold on; plot(pto(1), pto(2), 'xr'); else errordlg('Por favor, digite um número válido de estações.', 'Erro'); return; end for j=2:numEst last = pto; pto = ginput(1); plot(pto(1), pto(2), 'xr'); line([last(1) pto(1)], [last(2) pto(2)]); d = ( norm(last-pto) / handles.px2min ) * 1852; text(pto(1)+(last(1)-pto(1))/2, pto(2)+(last(2)-pto(2))/2, ... sprintf('%.2fm', d), 'backgroundcolor', 'y'); end hold off;
Se você quiser transformar uma interface gráfica em um programa de verdade (que pode ser executado em outros computadores, mesmo sem o MATLAB) você pode usar o MATLAB Compiler, digitando o seguinte no prompt do MATLAB (interface.m é o nome do arquivo M, não é necessário especificar o arquivo FIG correspondente):
mcc -m interface.m
A opção -m diz que queremos um programa standalone, ou seja, que funcione sozinho, independente do MATLAB. Na verdade, ele não será totalmente independente, ele requerirá a instalação do MCR (MATLAB Compiler Runtime), mas você poderá distribuir seu programa e o MCR livremente e dentro da lei, pois o pessoal da MathWorks deixa você distribuir o MCR para qualquer um (apenas o MCR). Consulte a documentação para saber mais.
Em Windows, será criado o arquivo interface.exe na mesma pasta na qual está o arquivo M, em Linux será criado o arquivo binário interface, também na mesma pasta do arquivo M.