Nesta aula veremos exemplos rápidos de como construir interfaces modais que retornam informação ao processo chamador. Por exemplo, como vimos há algumas aulas, o MATLAB possui janelas para questionamento (questdlg), porém, a própria janela aberta com essa função apresenta limitações quanto ao número de botões que contém (no caso, somente três).
O guide possui um template pronto para janelas desse tipo, porém, faremos nossa janela a partir de uma interface em branco. Isso tornará os exemplos mais simples.
Deve-se lembrar aqui a diferença entre uma figura modal e uma não-modal. Uma interface modal não permite a manipulação de outras janelas enquanto o usuário não atender à solicitação da janela corrente. Isso não significa que a execução do programa será interrompida. Vale lembrar que para tanto deve-se utilizar a função uiwait, que interrompe a execução normal do código.
Outro ponto que deve ser lembrado é que o guide faz uso de uma estrutura para que informação seja passada entre as funções de retorno no tratamento dos eventos. Essa estrutura recebe o nome de handles. Vale salientar que a estrutura handles pode ser modificada de maneira e inserir as variáveis necessárias para a aplicação, bastando adicionar o nome da variável concatenada ao nome de estrutura, por exemplo, handles.minha_variavel.
Com essas informações em mente, é possível continuar com nossas explicações.
Vale uma atenção especial à duas funções da interface gráfica. Quando a função é executada, usualmente a figura é carregada e a função OpeningFcn é executada, de modo a preparar a inteface gráfica para o usuário.
Em uma aplicação não-modal e que não espera a resposta do usuário, a função
OutputFcn é executada logo após OpeningFcn. Lembre-se que a janela trabalha em conjunto com as funções no arquivo .m com o mesmo nome, invocando as callbacks do arquivo quando necessário. Observe que a janela de comando está acessível na execução de uma interface não- modal e que não utiliza a função uiwait. Note que a função OutputFcn utiliza varargout, um vetor de células para que handles.output (variável padrão) seja retornada. É possível alterar o valor de handles.output ou ainda criar uma nova variável de saída.
Para melhor compreender o mecanismo, crie uma interface com apenas um botão (como a na figura abaixo) e salve-a em uma pasta.
2 AULA 20 – INTERFACES GRÁFICAS III
Na função de abertura da interface, adicione as linhas abaixo:
function retorno_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn. % hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to retorno (see VARARGIN)
handles.tempo = tic;
% Update handles structure
guidata(hObject, handles);
Na função de saída, escreva o código:
function varargout = retorno_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
handles.output = toc(handles.tempo); %altera saída para verificar tempo % Get default command line output from handles structure
disp('Função de saída foi executada'); varargout{1} = handles.output
Note que a vírgula é omitida na última linha. Execute a aplicação e verifique a saída. Perceba que a função de saída é executada logo após a aplicação ser carregada.
Trata-se de uma aplicação não-modal que não aguarda que o usuário responda à solicitação do diálogo.
Para fazer com que a aplicação aguarde o comando do usuário, deve-se adicionar no final da função de abertura OpeningFcn o comando:
uiwait(handles.figure1); E deve-se utilizar o comando
uiresume(handles.figure1);
Para se retomar a execução normal da função associada à figura. Modifique a função de abertura como abaixo:
function retorno_OpeningFcn(hObject, eventdata, handles, varargin)
handles.tempo = tic; clc guidata(hObject, handles); uiwait(handles.figure1);
Para retomar a execução normal, adicione o código abaixo na função de callback do botão:
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)
Perceba que a aplicação apenas retornou quando a função uiresume foi executada. É possível fazer a figura modal, bastando adicionar à função de abertura:
set(handles.figure1,'WindowStyle','modal')
Note que a figura não é automaticamente fechada. Isso pode ser realizado mediante o comando delete. Altere a função de saída para o código abaixo:
function varargout = retorno_OutputFcn(hObject, eventdata, handles) handles.output = toc(handles.tempo);
disp('Função de saída foi executada'); varargout{1} = handles.output
delete(handles.figure1)
Outras callbaks que valem a pena serem estudadas são: KeyPressFcn,
KeyReleaseFcn e CloseRequestFcn. A primeira é executada quando uma tecla do teclado é pressionada, a segunda quando a tecla e solta e última quando o usuário tenta fechar a janela.
Observe a interface abaixo, cujas funções estão dispostas na seqüência.
function teste_OpeningFcn(hObject, eventdata, handles, varargin) handles.x = 0;
plot(handles.axes1,handles.x,0,'Marker','x');
set(handles.axes1,'Xlim',[-1.1 1.1],'Visible','off'); drawnow;
handles.output = hObject; guidata(hObject, handles);
set(handles.figure1,'WindowStyle','modal')
function varargout = teste_OutputFcn(hObject, eventdata, handles) varargout{1} = handles.output;
4 AULA 20 – INTERFACES GRÁFICAS III
function botao_esquerda_Callback(hObject, eventdata, handles)
if handles.x > -1
handles.x = handles.x - 0.1;
end
plot(handles.axes1,handles.x,0,'Marker','x');
set(handles.axes1,'Xlim',[-1.1 1.1],'Visible','off'); drawnow;
guidata(hObject,handles);
function botao_direita_Callback(hObject, eventdata, handles)
if handles.x < 1
handles.x = handles.x + 0.1;
end
plot(handles.axes1,handles.x,0,'Marker','x');
set(handles.axes1,'Xlim',[-1.1 1.1],'Visible','off'); drawnow;
guidata(hObject,handles);
function figure1_KeyPressFcn(hObject, eventdata, handles)
if isequal(get(hObject,'CurrentKey'),'leftarrow') if handles.x > -1
handles.x = handles.x - 0.1; end
plot(handles.axes1,handles.x,0,'Marker','x');
set(handles.axes1,'Xlim',[-1.1 1.1],'Visible','off'); drawnow;
elseif isequal(get(hObject,'CurrentKey'),'rightarrow') if handles.x < 1
handles.x = handles.x + 0.1; end
plot(handles.axes1,handles.x,0,'Marker','x');
set(handles.axes1,'Xlim',[-1.1 1.1],'Visible','off'); drawnow;
end
guidata(hObject, handles)
Atente que a função figure1_KeyPressFcn, pode ser criada através do inspetor de propriedades:
E
XERCÍCIOSExercício 1 Desenvolva uma interface de diálogo com 5 opções para responder à pergunta: O que você achou da disciplina? As opções são: Péssima, Ruim, Medíocre, Boa, Ótima. Faça com que a interface retorne o texto do botão.
Exercício 2 Considerando a função de transferência de segunda ordem apresentada abaixo: 𝐺𝐺(𝑠𝑠) = 𝑠𝑠2 𝜔𝜔𝑛𝑛2
+ 2𝜉𝜉𝜔𝜔𝑛𝑛𝑠𝑠 + 𝜔𝜔𝑛𝑛2
A equação de magnitude da função de transferência em função da freqüência ω é dada pela equação:
|𝐺𝐺(𝑗𝑗𝜔𝜔)| = 𝜔𝜔𝑛𝑛
2
�(𝜔𝜔𝑛𝑛2− 𝜔𝜔2)2+ (2𝜉𝜉𝜔𝜔𝑛𝑛𝜔𝜔)2
A magnitude é calculada em decibéis, fazendo:
20log(|𝐺𝐺(𝑗𝑗𝜔𝜔)|)
Trace um gráfico com a magnitude em decibéis em função da freqüência ω. Desenvolva uma interface gráfica que permita ao usuário manipular o fator de amortecimento (0.001 até 10) e a freqüência natural de ressonância de 0.1 até 10, observando o impacto de cada uma das variáveis no gráfico.
1 AULA 5 – Respostas dos Exercícios