Đối tượng Canvas có thể hỗ trợ bắt sự kiện dưới 2 cấp độ:
Bắt sự kiện cấp cao: thêm một hay nhiều đối tượng Commmand vào đối tựong Canvas và bắt sự kiện thông qua các Command này (dùng CommandListener).
Bắt sự kiện cấp thấp: bắt sự kiện các phím số trên thiết bị cũng như các sự kiện con trỏ, sự kiện trong game…..
Bắt sự kiện cấp cao.
Lớp Canvas cũng là lớp con của Displayable như lớp Screen do đó cũng kế thừa các phương thức hỗ trợ Command như lớp Screen gồm:
o addCommand(Command)
o isShown()
o removeCommand(Command)
o setCommandListener(CommandListener)
Ví dụ:
class TestCanvas extends Canvas implements CommandListener {
private Command cmExit; // Exit MIDlet
CmExit = new Command(“Exit”, Command.EXIT, 1); addCommand(cmExit);
setCommandListener(this);
public void commandAction(Command c, Displayable d) {
if(c == cmExit) { // xử lý ……….. } }
Bắt sự kiện cấp thấp:
Sử dụng mã phím (key code).
Mã phím là các giá trị nguyên gán cho các phím tương ứng trong thiết bị di động.
Các phím này được gán với các tên tương ứng cho dễ nhớ: Ví dụ:
public static final int KEY_NUM0 = 48; public static final int KEY_NUM1 = 49;
Bảng mã phím các phím bàn phím ITU-T (0-9, *, #)
Lớp Canvas hỗ trợ việc bắt sự kiện các phím này bằng các phương thức: Các phương thức keyPressed(), keyReleased() và keyRepeated() được khai báo trong lớp Canvas với thuộc tính protected.
protected void keyPressed(int keyCode) {
// ………. };
protected void keyReleased (int keyCode) {
// ………..… };
protected void keyRepeated(int keyCode) {
// …………. };
Do đó, muốn bắt sự kiện nào thì ta cần khai báo phương thức tương ứng trong lớp kế thừa Canvas và viết code xử lý cho phương thức đó.
Ví dụ:
protected void keyPressed(int keyCode) {
switch(keyCode) {
KEY_NUM1:// ……. Break; KEY_NUM2:// ……. Break; KEY_NUM3:// ……. Break; //………. } } 4.3.1.4. Game action:
MIDP cũng hỗ trợ lập trình game bằng cách định nghĩa sẵn một bộ các phím bấm xử lý sự kiện game. Mỗi sự kiện game cũng được gán bởi một số nguyên như sự kiện phím bấm. Các sự kiện chính bao gồm các sự kiện sang trái, sang phải, lên xuống và enter. Với các loại sự kiện có hỗ trợ các phím di chuyển thì các sự kiện này sẽ được gán trực tiếp cho các phím đó. Nếu không, có thể gán các sự kiện này với các phím số 2, 4, 5, 8, 5.
Các phương thức sử dụng cho lập trình game.
Ví dụ:
// Lấy mã phím tương ứng cho các hành động trong game: int keyFire = getKeyCode(FIRE);
int keyFire = getKeyCode(FIRE); // ………..
// Lấy lấy loại hành động game để xử lý protected void keyReqeated(int keyCode) { switch(getGameAction(keyCode)) { case Canvas.FIRE: // ………. break; case Canvas.LEFT: // ………. break;
//……… }
}
Một hành động game có thể gán cho nhiều phím bấm, chẳng hạn gán cho cả phím chức năng (trái, phải, lên, xuống) lẫn các phím số. Khi đó, người dùng có thể bấm phím chức năng sang trái hay phím số 4 đều phát sinh sự kiện game LEFT như nhau.
Sự kiện con trỏ:
MIDP cũng hỗ trợ các phương thức để lập trình trên thiết bị di động có sử dụng con trỏ như chuột hay màn hình cảm ứng.
Các sự kiện con trỏ cũng được xử lý tương tự các sự kiện phím bấm. Nếu thiết bị có hỗ trợ xử lý sự kiện con trỏ, các phương thức pointerDragged(), pointerPressed(), pointerReleased() sẽ được gọi khi người dùng rê, nhấp nút hay nhả con trỏ. Các phương thức này cũng được khai báo trong lớp Canvas với thuộc tính protected nên nếu muốn xử lý sự kiện con trỏ cho chương trình phải báo hàm với tên tương ứng trong lớp con của chương trình và viết xử lý bên trong.
Ví dụ:
protected void pointerPressed(int x, int y) {
// xác định vị trí điểm đầu startx = x;
starty = y; }
protected void pointerDragged(int x, int y) { // xác định vị trí điểm hiển thị currentx = x; currenty = y; repaint(); }
{ // xác định vị trí điểm cuối endx = x; endy = y; repaint(); } 4.3.2. Graphics:
Đối tượng Graphics dùng để vẽ lên màn hình Canvas. Lớp Graphics cung cấp sẵn trên 30 phương thức hỗ trợ vẽ các đối tượng hình học cơ bản (đường thẳng, đường tròn, hình chữ nhật….), text cũng như điều khiển màu sắc, font chữ….
Có thể sử dụng lớp Graphics trong hai trường hợp: Trong phương thức paint() của lớp Canvas:
protected void paint(Graphics) {
// ……… }
Đối tượng graphics này chỉ có giá trị bên trong phương thức paint(), ra khỏi phương thức này thì còn dùng để vẽ lên Canvas được nữa.
Trong các đối tượng mutable image:
Các immutable image thường được tạo ra từ file hay resource, có tính cố định, không thay đổi. Do đó, người ta thường dùng immutable image làm biểu tượng cho các thành phần trong ChoiceGroup, Form, List hay Alert.
Ngược lại, đối tượng mutable image chỉ là một vùng nhớ có kích thước cố định được cấp khi khởi tạo.
Ví dụ:
Image iImage = Image.create.createImage(80, 20); Graphics gGraphics = iImage.getGraphics();
Đối tượng Graphics được tạo ra theo cách này có giá trị cùng với đối tượng Image. Khi đối tượng Image bị hủy thì đối tượng Graphics tương ứng cũng bị hủy theo.
(Grayscale là một số nguyên kiểu int có giá trị từ 0 đến 255 biểu thị độ sáng của màu xám (shade of gray)).
4.3.2.1. Color:
Màu sắc trong đối tượng Graphics được tạo ra từ 3 màu cơ bản là đỏ, xanh lục và xanh dương (RGB) được biểu diễn bởi 24 bit màu, mỗi màu chiếm 8bit. Nếu thiết bị không hỗ trợ hiển thị màu hay chỉ hỗ trợ với số màu ít hơn thì thiết bị sẽ tự chuyển đổi để hiển thị màu gần nhất so với yêu cầu. Grayscale dùng để hiển thị các sắc độ màu khác nhau trên màn hình đen trắng.
Khi gán màu cho đối tượng Graphics, có thể dùng một trong 2 cách:
Kết hợp 3 màu (đỏ, xanh dương và xanh lục) trong một số nguyên kiểu int hay biểu diễn từng thành phần trong từng số int. Khi kết hợp 3 màu với nhau, mỗi màu được biểu diễn bởi 8bit và xếp theo thứ tự từ cao xuống thấp là đỏ, xanh lục và xanh dương. Do đó, để kết hợp 3 giá trị màu này vào một số nguyên kiểu int, ta phải dịch bit để có kết quả chính xác. Giá trị màu đỏ sẽ dịch trái 16bits, giá trị màu xanh lục dịch trái 8bits và giá trị màu xanh dương chiếm 8bits thấp nhất.
Ví dụ:
int red = 0; int green = 127; int blue = 255;
int color = (red << 16) | (green << 8) | blue; g.setColor(color);// g là đối tượng kiểu Graphics. // Gán giá trị cho từng màu cơ bản riêng biệt: int red = 0;
int green = 127; int blue = 255;
g.setColor(red, green, blue);
Khi lấy giá trị màu, ta cũng có thể lấy ra dưới dạng kết hợp hay từng màu riêng biệt. Nếu lấy từng giá trị màu dưới dạng kết hợp, để có được giá trị màu cho từng màu cơ bản cần phải bỏ đi các bit không thích hợp.
Int color, red, green, blue;
Color = g.getColor(); // g là đối tượng kiểu Graphics. Red = (color & 0xFF00) >> 16;
Green = (color & 0xFF00) >> 8; Blue = color & 0xFF;
Có thể kiểm tra thiết bị di động có màn hình màu không bằng phương thước: Javax.microedition.lcdui.Display.isColor();
Ngoài ra, có thể lấy số màu thiết bị có hỗ trợ bằng phương thức.
Javax.microedition.lcdui.Display.numColors() nếu thiết bị chỉ có màn hình đen trắng thì giá trị màu trả về là giá trị grayscale mặc định.
4.3.2.2. Nét vẽ:
Kiểu nét vẽ (Stoke style): Khi vẽ đường thẳng, đường tròn, hình chữ nhật ta có thể lựa chọn kiểu nét vẽ là nét liền (Graphics.SOLID) hay cách khoảng (Graphics.DOTTTED). Nét liền là giá trị mặc định của các kiểu vẽ.
Bảng 30:Các phương thức vẽ trong lớp javax.microedition.lcdui.Graphics.
Phương thức Chức năng
void drawChar (char character, int x, int y, int anchor)
Vẽ ký tự character lên màn hình
void drawChars (char[] data, int offset, int length, int x, int y, int anchor)
Vẽ chuỗi ký tự data với chiều dài length từ vị trí offset lên màn hình
void drawString (String str, int x, int y, int anchor)
Vẽ chuỗi str lên màn hình
void drawSubstring (String str, int offset, int len, int x, int y, int anchor)
Vẽ chuỗi con có chiều dài len , từ vị trí offset của chuỗi str lên màn hình
Font getFont() Lấy đối tượng Font hiện tại
void setFont () Gán Font cho đối tượng Graphics
Ví dụ:
g.drawArc(5,5,75,0,255);
g.fillArc(5, 5, 75, 100, 0, 360); g.fillArc(75, 100, 75, 50, 90, 300); Hình chữ nhật gồm 4 loại:
Hình chữ nhật thường, không tô.
Hình chữ nhật góc cong, không tô.
Hình chữ nhật thường, tô đặc. Hình chữ nhật gốc tròn, tô đặc.
Hình chữ nhật góc tròn là hình chữ nhật trong đó các góc được vẽ theo dạng đường cong chứ không phải là góc hình vuông như hình chữ nhật bình thường. Trong đó, các góc cong là ¼ đường cong nội tiếp hình chữ nhật kích thước rộng dài tương ứng là arcW và arcH.
Ví dụ: g.drawRect(1, 1, 60, 40); g.drawRoundRect(70, 50, 60, 40, 30, 40); g.fillRect(1, 1, 60, 40); g.fillRoundRect(70, 50, 60, 40, 30, 40); Các phương thức hỗ trợ vẽ text:
Khi vẽ text lên màn hình, bất kể đó là một ký tự hay một chuổi ký tự, ta phải cung cấp đủ ba tham số: x, y, anchor. Trong đó, (x, y) là tọa độ điểm gốc, và anchor là vị trí tương đối của điểm gốc so với đoạn text sẽ được hiển thị. Các vị trí tương đối của anchor đã định nghĩa sẵn trong lớp Graphics gồm:
Bảng 31:Các kiểu định dạng trong lớp javax.microedition.lcdui.Graphics.
Tên anchor Mô tả Vị trí
LEFT Lề trái của ký tự / chuỗi. chiều ngang
HCENTER điểm giữa của ký tự / chuỗi chiều ngang
RIGHT lề phải của ký tự / chuỗi chiều ngang
TOP điểm cao nhất của ký tự / chuỗi chiều dọc
BASELINE dòng chuẩn của ký tự / chuỗi chiều dọc
Khi sử dụng, biến anchor thường được kết hợp hai kiểu định vị theo chiều ngang và chiều dọc để được vị trí tương đối của điểm gốc.
Ví dụ:
// vẽ chuỗi “Hello J2ME” với góc trên trùng góc trái trên của màn hình. gr.drawString(str, 0, 0, Graphics.TOP | Graphics.LEFT);
// vẽ chuỗi “Hello J2ME” ngay giữa màn hình, nghĩa là điễm giữa trùng với điểm giữa của màn hình.
gr.drawString(str, getWidth()/2, getHeight()/2, Graphics.BASELINE |
Graphics.HCENTER);
// vẽ chuỗi “Hello J2ME” với góc phải dưới trùng góc phải dưới của màn hình. gr.drawString(str, getWidth(), getHeight(), Graphics.BOTTOM |
Graphics.RIGHT);
4.3.2.3. Font chữ:
Bảng 32:Các phương thức xử lý Font.
Phương thức Chức năng
static Font getFont (int face,
int style, int size)
Tạo đối tượng Font
static Font getDefaultFont ()
Tạo đối tượng Font mặc định
int getFace () lấy face hiện tại
int getStyle () lấy kiểu chữ (đậm, in nghiêng, gạch dưới)
int getSize () lấy cỡ chữ
boolean isPlain () kiểm tra có đang dùng kiểu chữ thường không
boolean isBold () kiểm tra có đang dùng kiểu chữ đậm không
boolean isItalic () kiểm tra có đang dùng kiểu chữ in nghiêng không
boolean isUnderlined () Kiểm tra có đang dùng kiểu chữ gạch dưới không
int getHeight () lấy kích thước font (khoảng cách giữa 2 dòng chữ)
int getBaselinePosition () lấy độ cao chữ
int charWidth (char ch) lấy độ rộng của ký tự ch
int charsWidth (char[] ch, int
offset, int length)
lấy độ rộng của chuỗi ký tự ch dạng mảng char
int substringWidth (String str, int offset, int length)
lấy độ rộng chuỗi con của chuỗi ký tự ch dạng String bắt đầu từ vị trí offset với độ dài length
Lớp Font không có phương thức khởi tạo nghĩa là không cần new để tạo đối tượng mới, thay vào đó, ta gọi thực hiện một trong hai phương thức getFont() hay getDefaultFont() để tạo đối tượng Font.
Các thuộc tính cần quan tâm khi tạo mới một font gồm: face, kiểu chữ (style) và kích thước. Các định dạng của mỗi loại thuộc tính đã được định nghĩa sẵn trong lớp Font, gồm:
Bảng 33:Các kiểu định dạng trong cho lớp Font.
Loại thuộc tính Tên thuộc tính Mô tả Giá trị
FACE_SYSTEM 0 FACE_MONOSPACE 32 Face FACE_PROPORTIONAL 64 STYLE_PLAIN chữ thường 0 STYLE_BOLD in đậm 1 STYLE_ITALIC in nghiêng 2 Style STYLE_UNDERLINED Gạch dưới 4 SIZE_SMALL Cỡ chữ nhỏ 8 SIZE_MEDIUM cỡ chữ trung bình 0 Size SIZE_LARGE Cỡ chữ lớn 16
Trong đó, thuộc tính face và cỡ chữ của font chỉ được sử dụng duy nhất một loại định dạng cho một đối tượng. Riêng với thuộc tính kiểu chữ, có thể kết hợp các định dạng trong cùng một đối tượng Font bằng toán tử OR.
Ví dụ:
// Tạo đối tượng Font cót thuộc tính Face kiểu system, cỡ chữ trung bình và có kiểu chữ in nghiêng và đậm.
Font font = Font.getFont (Font.FACE_SYSTEM, Font.STILE_BOLD | Font.STYLE_ITALIC | Font.STYLE_UNDERLINED,
// Lấy thuộc tính face, cỡ chữ của đối tượng Font. int face = font.getFace();
int size = font.getSize();
// kiểm tra kiểu chữ của đối tựơng font // cách 1:
int style = font.getStyle();
if(style == (Font.STYLE_BOLD | Font.STYLE_ITALIC)) // làm ……….
// Cách 2:
if( font.IsBold() && font.IsItalic() ) // làm ………..
4.3.2.4. Vẽ các đối tượng hình ảnh (Image):
Lớp Graphics hỗ trợ một phương thức duy nhất để vẽ hình lên màn hình, đây là bước cuối cùng để vẽ một hình ảnh lên màn hình, các bước trước đó dùng để tạo đối tượng Image cũng như load hình ảnh lên đối tượng đó. Đối tượng Image gồm hai loại: có thể thay đổi hình ảnh (Mutable Image) và hình ảnh cố định (Immutable Image).
Các bước để vẽ đối tượng Image lên màn hình:
Immutable Image:
1. Tạo đối tượng hình lên ảnh (thường là load trực tiếp từ file): Image img = Image.createImage(“\imageTest.png”); 2. Hiển thị đối tượng lên màn hình:
protected void paint (Graphics g) {
// làm ………….
g.drawImage(img, 10, 10, Graphics.LEFT | Graphics.TOP); }
Mutable Image:
Khởi tạo đối tựơng, yêu cầu chương trình cấp một vùng nhớ với kích thước
cho trước của hình ảnh:
Vẽ hình lên đối tượng:
// Lấy đối tượng Graphics tương ứng của đối tượng Image: Graphics g = img.getGraphics();
// Dùng đối tượng Graphics vừa lấy vẽ các hình lên đối tượng Image: g.fillRoundRect(0, 0, 50, 50, 20, 20);
//…………
Hiển thị hình vừa vẽ lên màn hình:
protected void paint(Graphics g){ // Gì gi đó đi
g.drawImage(img, 10, 10, Graphics.VCENTER | Graphics.HCENTER);
}
Khi gọi phương thức vẽ đối tượng Image lên màn hình, ta cũng phải truyền các tham số x, y, anchor như khi vẽ text. Tuy nhiên, các loại anchor của hình ảnh tương đối khác với text, đó là không sử dụng anchor BASELINE (đường chuẩn của ký tự / chuỗi) mà thay vào đó là VCENTER để chỉ điểm giữa theo chiều dọc của hình ảnh.
4.3.2.5. Các phương thức tịnh tiến của đối tượng:
Để đơn giản khi biểu diễn sự tịnh tiến của các đối tượng hình ảnh trên màn hình, lớp Graphics cho phép người lập trình vẽ các đối tượng ở vị trí cố định. Khi cần tịnh tiến các đối tượng trên màn hình thì chỉ cần tịnh tiến gốc tọa độ đến vị trí mới, các hình ảnh của đối tượng Graphics sẽ tịnh tiến theo.
Bảng 34:Các phương thức tịnh tiến đối tượng.
Phương thức Mô tả
void translate(int x, int y) tịnh tiến điểm gốc (0, 0) của đối tượng Graphics đến vị trí (x,y)
int getTranslateX() lấy khoảng cách trên trục hoành đã bị tịnh tiến
int getTranslateY() lấy khoảng cách trên trục tung đã bị tịnh tiến
Khi gọi thực hiện phương thức translate() để tịnh tiến ảnh trên màn hình thì chỉ có gốc tọa độ bị thay đổi vị trí, và cũng chỉ có ý nghĩa trong lần gọi hàm đó. Nếu
gọi thực hiện phương thức repaint() mà không gọi translate() lần nữa thì toạ độ gốc sẽ trở về vị trí (0, 0) ban đầu.
Ví dụ:
// Khi người dùng nhấn phím mũi tên xuống thì tịnh tiến hình ảnh xuống 1pixel:
protected void keyPressed(int keyCode){ switch(getGameAction( keyCode)){
// ……… Case DOWN:
if((translatey + img.getHeight() + 1) > getHeight()) translatey = 0; else translatey ++; break; // ………. } repaint(); }
protected void paint(Graphics g){ if(im != null) {
// Xóa màn hình
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight()); // tịnh tiến gốc tọa độ.
g.translate(translatex, translatey); // luôn vẽ ở vị trí 0, 0.
g.drawImage(im, 0, 0, Graphics.LEFT | Graphics.TOP); }
4.3.2.6. Vùng xén (Clipping regions):
Mỗi lần gọi phương thức paint(), toàn bộ màn hình sẽ được vẽ lại. Vùng xén được dùng để giới hạn vùng cần vẽ lại, làm giảm thời gian cần để vẽ lại màn hình. Bình thường, nếu không tạo vùng xén thì vùng xén mặc định sẽ là hình chữ nhật
bao của màn hình (tức các hình chữ nhật (0, 0, Canvas.getWidth(),
Canvas.getHeight())).
Bảng 35:Các phương thức hỗ trợ xén.
Phương thức Mô tả void setClip (int x, int y, int