User Interaction
Programação por Objectos 2011/12, Taguspark
Pedro Reis dos Santos
Este documento pretende descrever brevemente o funcionamento da interface
utilizador utilizada para desenvolver aplicações na disciplina de
Programação por Objectos.
As classes que constituem a interface utilizador são distribuídas em
código fonte Java no pacote pt.utl.ist.po.ui
A interacção é realizada apenas com menus, forms e displays.
O menu é uma lista de opções que o utilizador pode escolher.
A form permite ao utilizador introduzir dados simples: números inteiros ou
reais, cadeias de caracteres ou valores booleanos (sim ou não).
O display é utilizada para informar o utilizador dos resultados da
interacção e é apenas constituída por cadeias de caracteres.
A interface utilizador disponibilizada procura facilitar o teste automático
da funcionalidade dos projectos desenvolvidos, suportar diferentes interfaces
e garantir a independência entre o núcleo do projecto e a sua interface
gráfica.
O núcleo é um conjunto de classes que modela e realiza o problema proposto.
A interface dá um aspecto visível possível através do qual se podem realizar
pedidos ao núcleo.
Desta forma, o núcleo nunca deve aceder à interface utilizador.
Da mesma forma, a interface utilizador não deve realizar operações de cálculo
ou gestão mas apenas recolher dados, passá-los a um ou mais métodos do
núcleo, e apresentar os resultados obtidos do núcleo.
Os exemplos das aulas prática bank e editor fornecem exemplos
simples para a realização de projectos mais complexos que devem ser
analisados para compreender os conceitos expostos neste documento.
A interligação entre o núcleo e a interface utilizador
Se o núcleo não depende da interface utilizador utilizada, deve ser esse
núcleo da aplicação a ser criado primeiro.
Esse núcleo, aqui designado por App, deve ser depois passado à
interface, para que esta possa fazer os pedidos e recolher os resultados.
O menu inicial, aqui designado por AppMenu, é uma classe que extende
a classe disponibilizada pt.utl.ist.po.ui.Menu.
A colocação de um título é facultiva e serve para identificar a janela
de interacção em algumas interfaces gráficas.
Para activar o menu, tornando-o visível e permitindo ao utilizador a
selecção de uma opção, basta invocar o método open().
A interacção termina com a invocação do método IO.close(), o que
permite libertar recursos como, por exemplo, janelas em ambientes gráficos.
App app = new App();
Menu m = new AppMenu(app);
IO.setTitle(title);
m.open();
IO.close();
Construção de um Menu
Os menus são classes derivadas da classe disponibilizada
pt.utl.ist.po.ui.Menu.
O construtor da classe recebe o título do menu (String) e um vector
de opcões (Command[]).
Cada uma das opções do menu é uma classe derivada da class disponibilizada
pt.utl.ist.po.ui.Command.
Estas opções podem ser realizadas por classes com nome, como as classes
Opçao2 ou SubMenu do exemplo abaixo, ou como uma classe anónima.
Em qualquer dos casos, a classe base Command deverá realizar o
método execute(), a ser invocado quando o utilizador selecciona
essa opção no menu.
Para que nesse método se possa aceder ao núcleo da aplicação, a classe
Command necessita ser parametrizada com a classe principal da
aplicação, ou eventualmente uma outra classe.
Uma instância deste tipo parametrizado deverá ser passada no construtor
da classe Command e acedida dentro do método execute()
através do método entity().
A operação entry(2).invisible() torna a segunda opção do
menu não seleccionável, até que o método visible() seja invocado.
public class AppMenu extends Menu {
public AppMenu(App app) {
super(MenuEntries.TITLE, new Command>[] {
new Command (false, "option title", app) {
public final void execute() {
App nucleo = entity();
Display d = new Display(title());
d.add("MyMenu.execute() called");
d.display();
}
},
new Opcao2(b),
new SubMenu(b)
});
entry(2).invisible();
}
}
Se uma classe derivada de Command não for anónima será codificada
separadamente.
A estrutura é idêntica ao exemplo anónimo acima, mas o construtor aparece
explicitamente.
Qualquer uma das opções de um menu pode ser um outro menu, cuja operação
de execute() deverá invocar o método open() do outro menu
para o activar.
Quando esse outro menu terminar, o controlo regressa ao menu actual.
public class SubMenu extends Command {
public AppMenu(App app) {
super(false, "SubMenu title, app);
}
public final void execute() throws InvalidOperation {
Menu m = new OtherMenu(entity());
m.open();
}
}
Apresentação de mensagens ao utilizador
A apresentação de mensagens para o utilizador realiza-se através da classe Display,
onde o método display(boolean force) apresenta o texto recolhido pelos métodos
add(String) e addNewLine(String).
A utilização da opção force executa a operação mesmo que
não tenha sido adicionado texto, enquanto o método addNewLine(String) cria uma nova
linha antes de adicionar o texto passado como argumento.
Pedido de valores ao utilizador
Para obter dados do utilizador, para definir pesquisas ou criar objectos,
por exemplo, é necessário utilizar forms.
Uma Form é uma classe que agrupa diversos pedidos numa só interacção.
Os pedidos resumem-se a valores de quatro tipos da linguagem Java:
int, real, boolean e String.
Para cada valor a pedir ao utilizador deverá ser criada uma instância das
classes InputInteger, InputFloat, InputString e
InputString, respectivamente.
Cada um dos construtores dessas classes recebe a Form onde deve ser
integrado o pedido e uma mensagem descritiva do pedido.
Existe ainda um separador, designado por InputNone que não pede
qualquer valor.
O método parse() da Form efectua o pedido ao utilizador,
podendo os valores ser recolhidos posteriomente através do método
value() de cada uma das instâncias de Input introduzidas na
Form.
public final void execute() throws InvalidOperation {
Form f = new Form("Titulo");
InputInteger id = new InputInteger(f, "Introduza um valor inteiro");
InputFloat real = new InputFloat(f, "Distância");
InputNone sep = new InputNone(f, "-----");
InputString str = new InputString(f, "Nome");
InputBoolean sn = new InputBoolean(f, "OK?");
f.parse();
IO.message("Id = " + id.value() + " Real = " + real.value() +
" Str = " + str.value() + " OK = " + sn.value());
}
Interfaces disponíveis
O modo normal de funcionamento da interface utilizador é o modo texto.
Este modo é o utilizado para efectuar os testes automáticos, e manuais,
pelo que ao desenvolver o projecto deve garantir o bom da aplicação neste
modo.
A execução da aplicação neste modo deve ser efectuada numa janela de
texto e não necessita de quaisquer parâmetros específicos.
java aplic.Main
Notar que se a variável de ambiente CLASSPATH não estiver
correctamente definida é necessário indicar o seu valor em cada
invocação.
java -cp . aplic.Main
Para efectuar testes de uma forma automatizada, incluindo os testes
disponibilizados ao longo do semestre, deve ser definidas duas variáveis
de ambiente.
Estas variáveis, designadas por in e out, permitem que a
interface utilizador redireccione, quando em modo texto, a entrada de
valores a partir de um ficheiro (in.txt) bem como a recolha dos
resultados (out.txt), respectivamente.
java -Din=in.txt -Dout=out.txt aplic.Main
A construção de um ficheiro jar (Java ARchive) permite
agrupar vários ficheiros compilados (.class) num só ficheiro.
Para que este ficheiro possa ser executado como uma aplicação é
necessário declarar um manifesto (MANIFEST.MF) onde se indica,
por exemplo, a classe de arranque (Main-Class) ou outros ficheiros
.jar a utilizar (Class-Path)
Main-Class: aplic.Main
Class-Path: pt.jar
O ficheiro .jar é criado com o comando
jar -cfm aplic.jar MANIFEST.MF *.class
Onde *.class representa todos os ficheiros da aplicação.
A aplicação pode agora ser invocada com
java -jar aplic.jar
Não confundir este ficheiro com um outro .jar que contém apenas
os ficheiros fonte (.java) a submeter para avaliação.
A utilização da interface gráfica swing é efectuada através da
atribuição à variável de ambiente ui:
java -Dui=swing aplic.Main
Este é o comportamento por omissão no sistema windows quando
directamente invocado a partir do explorer, se o ficheiro jar
estiver correctamente construído e associação com o interpretador Java
definida.
Embora experimental, também é possível executar a aplicação a partir de
um browser utilizando um applet.
Para tal basta incluir a sua invocação num ficheiro de hipertexto
(.html).
Neste caso a execução já não se inicia pela rotina main() pelo que
a classe de arranque é sempre pt.utl.ist.po.ui.AppletInteraction.
Como parâmetro é necessário definir a localização da rotina main()
como valor do parâmetro mainClass.
<applet width=300 height=300 code="pt.utl.ist.po.ui.AppletInteraction" archive = 'aplic.jar'>
<param name="mainClass" value="aplic.Main" >
</applet>