Prosseguindo com os detalhes de como implementar aplicações Java ME que façam uso de telas sensíveis ao toque, hoje vamos ver uma forma de usar essas telas como entrada de dados: ter uma área da tela responsável por disparar uma ação, como um menu.
Também vamos mostrar como um menu desses pode ser construído de forma a se adaptar a mudanças de orientação da tela.
Primeiro vamos representar cada entrada do menu com a classe abaixo. A responsabilidade dela é saber pintar cada item e guardar o Command que será disparado ao se tocar na tela sobre esse item:
public class TouchItem {
Command command;
public TouchItem(Command command) {
this.command = command;
}
// para funcionar é preciso que o objeto
// Graphics seja ajustado de forma que
// a origem esteja no canto superior esquerdo
// e a area disponivel para pintura seja
// definida pelo clip
public void paint (Graphics g) {
g.drawString(command.getLabel(),
g.getClipWidth() / 2, g.getClipHeight() / 2,
Graphics.HCENTER | Graphics.BASELINE);
g.drawRect(0, 0, g.getClipWidth(), g.getClipHeight());
}
}
Depois implementamos uma classe responsável por pintar todos os itens do menu. Essas duas primeiras classes também podem ser usadas para implementar a interface de jogos de tabuleiro, como Xadrez, por exemplo.
public class TouchGrid {
private final TouchItem items[][];
private int itemWidth, itemHeight;
private int x, y;
private int nextLine, nextColumn;
public TouchGrid(int x, int y, int width, int height, int columns, int lines) {
this.items = new TouchItem[columns][lines];
setRectangle(x, y, width, height);
}
public void setRectangle (int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.itemWidth = width / this.items.length;
this.itemHeight = height / this.items[0].length;
}
// preenche as colunas de uma linha antes de
// passar para a proxima linha. Quatro chamadas
// consecutivas resultam na seguinte apresentacao
// [ 1, 2 ]
// [ 3, 4 ]
public void add (TouchItem item) {
this.items[nextColumn][nextLine] = item;
nextColumn = (nextColumn + 1) % items.length;
if (nextColumn == 0) {
nextLine = (nextLine + 1) % items[0].length;
}
}
public void paint (Graphics g) {
Clip clip = new Clip(g);
int itemX = x;
for (int i = 0; i < items.length; i++) {
int itemY = y;
for (int j = 0; j < items[i].length; j++) {
if (items[i][j] != null) {
// define a area de pintura e
// desloca a origem
g.setClip(itemX, itemY, itemWidth, itemHeight);
g.translate(itemX, itemY);
items[i][j].paint(g);
// restaura o estado inicial
g.translate(-g.getTranslateX(), -g.getTranslateY());
clip.applyTo(g);
}
itemY += itemHeight;
}
itemX += itemWidth;
}
}
// aqui mapeamos o ponto pressionado na tela
// em um item do menu
public TouchItem getTouchItemAt (int x, int y) {
if (x < this.x || y < this.y) {
return null;
}
int i = (x - this.x) / this.itemWidth;
int j = (y - this.y) / this.itemHeight;
if (i >= items.length || j >= items[0].length) {
return null;
}
return items[i][j];
}
}
No código acima usamos a seguinte classe utilitária para guardar os valores da área de pintura e resetá-la:
public class Clip {
private int x, y;
private int width, height;
public Clip (Graphics g) {
x = g.getClipX();
y = g.getClipY();
width = g.getClipWidth();
height = g.getClipHeight();
}
public void applyTo (Graphics g) {
g.setClip(x, y, width, height);
}
}
Precisamos de uma classe que herda de Canvas para pintar o grid. Ela também será usada para criar as opções de menu:
public class TouchMenuCanvas extends Canvas {
private TouchGrid touchGrid;
private CommandListener commandListener;
public TouchMenuCanvas () {
final int columns = 2;
final int lines = 3;
int margin = getWidth() / 25;
// 2 = margens esquerda e direita
int width = getWidth() - (2 * margin);
// 2 = margens superior e inferior
int height = getHeight() - (2 * margin);
touchGrid = new TouchGrid(margin, margin, width, height, columns, lines);
for (int i = 0; i < lines * columns; i++) {
Command c = new Command("item " + (i+1), Command.SCREEN, 1);
touchGrid.add(new TouchItem(c));
}
}
// quando a orientação da tela muda precisamos
// atualizar as informações do grid
protected void sizeChanged(int width, int height) {
int margin = width / 25;
width = width - (2 * margin);
height = height - (2 * margin);
touchGrid.setRectangle(margin, margin, width, height);
}
// precisamos sobre-escrever esse metodo pois nao
// existe um metodo getCommandListener na API
public void setCommandListener(CommandListener listener) {
super.setCommandListener(listener);
commandListener = listener;
}
protected void paint(Graphics g) {
g.setColor(0xffffff); // white
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0); // black
this.touchGrid.paint(g);
}
protected void pointerPressed(int x, int y) {
TouchItem item = this.touchGrid.getTouchItemAt(x, y);
if (item != null) {
commandListener.commandAction(item.command, this);
}
}
}
Para finalizar o MIDlet para mostrar o canvas na tela:
public class TouchMenuMIDlet extends MIDlet implements CommandListener {
TouchMenuCanvas menuCanvas;
public TouchMenuMIDlet() {
menuCanvas = new TouchMenuCanvas();
menuCanvas.setCommandListener(this);
menuCanvas.addCommand(new Command("Exit", Command.EXIT, 1));
}
public void commandAction(Command c, Displayable d) {
if (c.getCommandType() == Command.EXIT) {
this.notifyDestroyed();
} else {
System.out.println(c.getLabel());
}
}
protected void destroyApp(boolean unconditional) {
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
Display.getDisplay(this).setCurrent(menuCanvas);
}
}
Abaixo telas da aplicação executando no emulador DefaultCldcPhone1 do Java Platform Micro Edition SDK 3.0 nas duas orientações.
![]() |
![]() |
Esperamos ter ajudado. Até a próxima.

home






blog de design do c.e.s.a.r.