1. Trang chủ
  2. » Công Nghệ Thông Tin

Multithreaded Graphics - Đa luồng gió trong đồ họa doc

30 623 5

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 30
Dung lượng 326,05 KB

Nội dung

Các phương pháp đa luồng trong tiếp cận đồ họa: + Khả năng vẽ lại trong paint + Khả năng vẽ trực tiếp trên cửa sổ Window + Bỏ qua lối update thông thường khi vẽ mà sử dụng paint để tăng

Trang 1

Multithreaded

Graphics

Đa luồng trong đồ họa

GV: Vũ Đình Hồng Khoa: CNTT – TỨD

Trang 2

NỘI DUNG CHÍNH

1 Các phương pháp đa luồng trong tiếp

cận đồ họa:

+ Khả năng vẽ lại trong paint

+ Khả năng vẽ trực tiếp trên cửa sổ Window

+ Bỏ qua lối update thông thường khi vẽ

mà sử dụng paint để tăng khả năng update

+ Kỹ thuật Double Buffering

2 Giảm thiểu giật và nháy hình (Reducing Flicker) trong đồ họa chuyển động

3 Hiện thực kĩ thuật Double Buffering

4 Kĩ thuật chuyển động hình ảnh

5 Điều khiển và kiểm soát các Timer trong chương trình

Trang 3

THREAD

Đơn luồng và Đa luồng ?

- Một “dòng điều khiển" trong chương trình

- Các chương trình thường chỉ có một dòng

điều khiển

- Với đa luồng, ta có thể có nhiều dòng điều

khiển được thực hiện cùng lúc trong 1 chương trình

Luồng trong Java ?

- Khi chương trình Java thực thi hàm main() tức

là tạo ra một luồng (luồng main) Trong luồng

main:

+ Có thể tạo các luồng con

+ Phải đảm bảo main là luồng kết thúc cuối cùng

+ Khi luồng main ngừng thực thi, chương trình

Trang 4

TIẾP CẬN ĐỒ HỌA

Các phương pháp chính

- Vẽ lại tất cả trong paint :

* Đơn giản và dễ dàng, tuy nhiên kéo theo là hình ảnh vẽ sẽ bị giật và màn hình đôi khi nhấp nháy.

- Vẽ trực tiếp trên cửa sổ Window:

* Dễ dàng, hiệu quả, không bị giật hình, tuy nhiên khi update kết quả không bảo đảm vẫn tồn tại ở lần vẽ sau.

- Tránh update, dùng paint để tăng khả năng

update:

* Loại bỏ hoàn toàn nhấp nháy và giật hình, có cải thiện hơn về mặt hiệu quả và mặt update, nhưng đòi hỏi hình ảnh không được chồng chéo lên nhau

- Kĩ thuật Double Buffering (tăng gấp đôi bộ đệm):

* Hầu như là hiệu quả và không gặp vấn đề khi hình ảnh có sự chồng chéo, phức tạp và tốn tài nguyên

Trang 5

VẼ LẠI TRONG PAINT

*Ý tưởng:

- Dùng các tác động người dùng để thay đổi những cấu trúc dữ liệu phi-đồ họa, sau đó gọi hàm vẽ lại repaint

- Phương thức repaint thiết lập 1 cờ, trong quá trình xử lý, dùng để gọi phương thức

update

- Phương thức update sẽ xóa màn hình, và gọi hàm paint

- Phương thức paint vẽ lại tất cả mọi thứ

Sửa dữ liệu -> repaint -> update -> paint

*Ưu điểm: Đơn giản

* Khuyết điểm: Chậm, giật và nháy hình

-

Trang 6

private ArrayList<SimpleCircle> circles;

public void init() {

circles = new ArrayList<SimpleCircle>();

addMouseListener(new CircleDrawer());

setBackground(Color.WHITE);

}

private class CircleDrawer extends MouseAdapter {

public void mousePressed(MouseEvent event) {

circles.add(new SimpleCircle(event.getX(), event.getY(), 25));

repaint();

} }

Trang 7

VÍ DỤ MINH HỌA

public void paint(Graphics g) {

for(SimpleCircle circle: circles) {

circle.draw(g);

} }

}

public class SimpleCircle {

// -private int x, y, radius;

public SimpleCircle(int x, int y, int radius) {

setX(x);

setY(y);

setRadius(radius);

} public void draw(Graphics g) {

g.fillOval(x - radius, y - radius, radius * 2, radius * 2);

}

}

Trang 8

VÍ DỤ MINH HỌA

Lưu trữ các kết quả của các lần vẽ trước trong cơ

sở dữ liệu thường trực của ứng dụng, sau đó là vẽ lại toàn bộ tất cả mỗi khi lệnh paint mới được gọi, kết quả là chỉ 1 bản vẽ tồn tại trong khi đó là sự chồng nhau và lộ ra của Window

Trang 9

VẼ TRỰC TIẾP TRÊN WINDOW

*Ý tưởng:

- Tạo 1 phương thức tùy ý nào đó (khác với

paint) có thể gọi được hàm getGraphics,từ đó lấy được đối tượng đồ họa của Window

- Sử dụng đối tượng này để vẽ đồ họa

- Hình ảnh sẽ bị mất nếu:

+ Window bị chồng hay bị lộ ra ngoài

+ Có phương thức update (ví dụ như

repaint)

*Ưu điểm: Nhanh chóng

* Khuyết điểm: Chỉ có tính tạm thời

Trang 10

VÍ DỤ MINH HỌA

public class Rubberband extends Applet {

private int startX, startY, lastX, lastY; p

private void drawRectangle(Graphics g, int startX, int startY, int stopX, int stopY ) {

private class RectRecorder extends MouseAdapter {

public void mousePressed(MouseEvent event) {

Trang 11

private class RectDrawer extends MouseMotionAdapter {

public void mouseDragged(MouseEvent event) {

int x = event getX();

}

Trang 12

VÍ DỤ MINH HỌA

Trang 13

BỎ QUA PHƯƠNG THỨC UPDATE

- Giả định các đối tượng được vẽ không

trùng nhau, khi vẽ 1 hình mới, ta sẽ xóa đi hình cũ bằng cách vẽ lên hình cũ một hình cùng màu với màu nền *Ưu điểm: Nhanh hơn, không giựt và nháy hình

* Khuyết điểm: Lỗi khi xử lý hình chồng nhau

Trang 14

VÍ DỤ MINH HỌA

public class Bounce extends Applet implements Runnable,

ActionListener{ private ArrayList<MovingCircle> circles;

private int width, height;

private Button startButton, stopButton;

private Thread animationThread = null;

public void init() {

setBackground(Color.WHITE);

width = getSize() width;

getSize().height = getSize().height;

circles = new ArrayList<MovingCircle>();

startButton = new Button("Start a circle");

Trang 15

animationThread new Thread(this);

animationThread.start();

} int radius = 25;

int x = radius + randomInt(width - 2 * radius);

int y = radius + randomInt(height - 2 * radius);

int deltaX = 1 + randomInt(10);

int deltaY = 1 + randomInt(10);

circles.add(new MovingCircle(x, y, radius, deltaX, deltaY)); } else if (event.getSource() == stopButton) {

if (animationThread != null) {

animationThread = null;

circles.clear();

} }

repaint();

}

Trang 16

VÍ DỤ MINH HỌA

public void run() {

Thread myThread = Thread.currentThread(); while(animationThread==myThread) {

public void paint(Graphics g) {

for(MovingCircle circle: circles) {

Trang 17

VÍ DỤ MINH HỌA

public void run() {

Thread myThread = Thread.currentThread(); while(animationThread==myThread) {

public void paint(Graphics g) {

for(MovingCircle circle: circles) {

Trang 18

VÍ DỤ MINH HỌA

Trang 19

TĂNG GẤP ĐÔI BỘ NHỚ ĐỆM

*Ý tưởng:

-Không vẽ trên cửa sổ window mà trên cửa

sổ Off-screen Pixmap, sau đó ta vẽ Pixmap này lên cửa sổ

*Các bước thực hiện:

1 Bỏ qua cập nhật, chỉ gọi hàm paint : Giảm giật và nháy hình

2 Tạo hình ảnh bằng createImage: hình ảnh này ở một cửa sổ khác, khi cửa sổ vẽ

thực sự được gọi thì hình ảnh mới hoàn toàn được gọi

3 Sử dụng getGraphics: để lấy đối tượng

đồ họa đã vẽ

Trang 20

TĂNG GẤP ĐÔI BỘ NHỚ ĐỆM

4 Với mỗi bước mới, xóa các hình ảnh và

vẽ lại tất cả lên trên: Nhanh hơn so với việc vẽ trên 1 cửa sổ đang hiển thị

5 Vẽ các hình ảnh Off-Screen lên cửa sổ

vẽ, sử dụng hàm drawImage

*Ưu điểm: Nhanh hơn, xử lý tốt những hình chồng nhau trên cửa sổ

* Khuyết điểm: Trở nên phức tạp hơn,

sử dụng Off-Screen Pixmap tốn bộ nhớ hơn, đôi khi việc giật và nháy hình sẽ xảy ra

(nếu tạo bộ đệm không tốt)

Trang 21

DOUBLE BUFFERING

public class DoubleBufferBounce extends Applet

implements Runnable, ActionListener {

private ArrayList<MovingCircle> circles;

private int width, height;

private Image offScreenImage;

private Graphics offScreenGraphics;

private Button startButton, stopButton;

private Thread animationThread = null;

public void init() {

Trang 22

DOUBLE BUFFERING

public void run() {

Thread myThread = Thread.currentThread();

while(animationThread==myThread) {

for(MovingCircle circle: circles) {

circle.move(width, height);

} repaint();

public void paint(Graphics g) {

offScreenGraphics.clearRect(0, 0, width, height); for(MovingCircle circle: circles) {

circle.draw(offScreenGraphics);

}

g.drawImage(offScreenImage, 0, 0, this);

}

Trang 23

DOUBLE BUFFERING

Trang 24

CHUYỂN ĐỘNG ĐỒ HỌA

*Ý tưởng:

- Sử dụng mảng array, ta lưu 1 chuỗi các

hình ảnh liên tục vào trong 1 mảng

- Khởi động một luồng tạo chu kì cho chuỗi hình ảnh và vẽ lên trên đối tượng đồ họa

* Mỗi lần luồng tạo chu kì với vòng lặp while, hàm repaint (gồm update) sẽ

được gọi để cập nhật hình ảnh lên cửa sổ vẽ

- Sử dụng cờ để ngưng chuyển động

Trang 25

CHUYỂN ĐỘNG ĐỒ HỌA

public class ImageAnimation extends Applet {

private static final int NUMDUKES = 2;

private Duke[] dukes;

private int i;

public void init() {

dukes = new Duke[NUMDUKES];

setBackground(Color.white);

} public void start() {

int tumbleDirection;

for (int i=0; i<NUMDUKES ; i++) {

tumbleDirection = (i%2 == 0) ? 1 : -1 ; dukes[i] = new Duke(tumbleDirection, this);

dukes[i].start();

} }

Trang 26

CHUYỂN ĐỘNG ĐỒ HỌA

public void update(Graphics g) {

paint(g);

}

public void paint(Graphics g) {

for ( i=0 ; i<NUMDUKES ; i++) { ){

if (dukes[i] != null) {

g.drawImage(Duke.images[dukes[i].getIndex( )],200*i, 0, this);

} }

Trang 27

TIMER

- Timer là một lớp tiện ích giúp cho việc lập lịch và kiểm soát việc thực thi một task vụ nào đó

- Một số hàm thông dụng trong Timer như:

* schedule lên lịch để thực thi TimerTask

khi nào bắt đầu, kết thúc hay lặp lại, …

* cancel dừng timer và hủy tất cả các task đã lên lịch trong timer

* purge xóa tất cả các task đã dùng trong hàng đợi timer

- TimerTask là một lớp trừu tượng

implement Runnable interface, nó giúp cho việc lập lịch thực thi các thread

Trang 28

PHƯƠNG PHÁP TIẾP CẬN TIMER

- Swing định nghĩa 1 lớp Timer là dùng để gọi lên 1 chu trình đơn và định kì nào đó, mỗi lần gọi lên lớp Timer là 1 ActionEvent sẽ được gọi

-Phương pháp tiếp cận của Timer trong

Trang 29

PHƯƠNG THỨC CỦA TIMER

- setRepeats:

* Thiết lập bộ đếm thời gian sẽ được gọi 1 lần hay theo định kì.

Trang 30

Q & A THANKS FOR LISTENING !!!

Ngày đăng: 07/08/2014, 15:21

TỪ KHÓA LIÊN QUAN

w