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

Bài giảng Bài 9: Tiếp tục cải tiến chương trình đồ họa liệt kê các số nguyên tố

20 64 0

Đ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 20
Dung lượng 175,19 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Bài giảng Bài 9: Tiếp tục cải tiến chương trình đồ họa liệt kê các số nguyên tố sau đây được biên soạn nhằm trang bị cho các bạn những kiến thức về lập trình đa luồng trong ứng dụng đồ họa, sử dụng ProgressMonitor, sử dụng SwingWorker, sử dụng PropertyChangeListener.

Trang 1

Bài 9: Tiếp tục cải tiến chương trình

đồ họa liệt kê các số nguyên tố

Lê Hồng Phương, Nguyễn Việt Hùng, Hà Mỹ Linh

phuonglh@gmail.com

Khoa Toán-Cơ-Tin học Trường Đại học Khoa học Tự nhiên Hà Nội

Trang 2

Nội dung

● Tiếp tục cải tiến chương trình liệt kê các số nguyên

tố trong bài giảng trước:

– Lập trình đa luồng trong ứng dụng đồ họa:

● Luồng đồ họa

● Luồng công việc

– Sử dụng ProgressMonitor

– Sử dụng SwingWorker

Trang 3

Nguyên tắc tách luồng

● Khi lập trình các ứng dụng có giao diện đồ họa, ta

cần chú ý nguyên tắc tách luồng:

Luồng đồ họa: vẽ, cập nhật các thành phần đồ

họa, nhận các sự kiện bấm phím, kích chuột

Luồng công việc: sử dụng để chạy các tác vụ

cần nhiều thời gian để thực hiện.

● Chú ý: luồng đồ họa còn được gọi là luồng phân phối

sự kiện: Event Dispatch Thread – EDT Mọi ứng

dụng đồ họa đều chạy trong một luồng đồ họa.

Trang 4

Nguyên tắc tách luồng

trước, ta không tách luồng

tác vụ liệt kê số nguyên tố sẽ mất nhiều thời gian

chương trình không hoạt động:

bất kì công việc nào khác trên giao diện

Trang 5

Nguyên tắc tách luồng

nguyên tố, chạy tách riêng khỏi luồng đồ họa

về kết quả thì sẽ thực hiện cập nhật kết quả trên giao diện bằng luồng đồ họa

chạy xong, có kết quả toàn bộ mới thực hiện cập nhật đồ họa

gian → Tăng tính tương tác của chương trình

Trang 6

Cách giải quyết cơ bản

luồng công việc kết thúc

thanh tiến trình (JProgressBar) hoặc một hộp thoại tiến trình (ProgressMonitor) chỉ định mức độ hoàn thành tác vụ của luồng công việc

luồng công việc giữa chừng bằng cách nhấn nút Cancer

Trang 7

Với những số n nhỏ thì

chương trình chạy nhanh, hộp thoại tiến trình không xuất hiện.

Nhập số n lớn, hộp

thoại tiến trình sẽ xuất hiện.

progressMonitor = new ProgressMonitor(

PrimeNumberFrame this ,

"Computing prime numbers " , "" , 0, 100);

private ProgressMonitor progressMonitor ;

Một trường của lớp PrimeNumberFrame

Trang 8

Nguyên tắc cập nhật đồ họa

● Việc cập nhật trạng thái của các thành phần đồ họa cần phải được thực hiện trong luồng đồ họa.

● Nếu luồng công việc thực hiện chức năng cập nhật

các thành phần đồ họa thì sẽ sinh ngoại lệ – chương trình bị lỗi.

● Lớp SwingWorker giúp lập trình viên quản lí cả luồng công việc và cập nhật đồ họa, tránh gây lỗi.

Trang 9

​Luồng khởi tạo

phát từ luồng bắt đầu, hay luồng khởi tạo (initial thread)

để sinh giao diện cho chương trình và chuyển đối tượng

đó vào chạy trong luồng đồ họa

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

PrimeNumberFrame app = new PrimeNumberFrame();

app.pack();

app.setVisible( true );

} });

Ở đây, ta sử dụng lớp nội không tên cài đặt giao diện Runnable (Chương trình

gọn hơn)

Trang 10

Luồng đồ họa

điều khiển bởi luồng này

→ xử lí sự kiện

– Bấm phím Ok → liệt kê các số nguyên tố

– Chọn mục thực đơn Exit → thoát chương trình

– Chọn mục thực đơn About → mở hộp thoại About

Trang 11

Luồng công việc

được sử dụng để thực hiện các tác vụ chậm

thuộc lớp javax.swing.SwingWorker

lớp này

sau

Trang 12

Luồng công việc

Phương thức doInBackground thực hiện tác vụ, trả

về kết quả để dùng trong các luồng khác (thường là dùng trong luồng đồ họa)

Phương thức done chứa các lệnh được thực hiện

trong luồng đồ họa khi thực hiện xong tác vụ.

Trang 13

Luồng công việc

● Chú ý:

Phương thức doInBackground cũng có thể trả các

kết quả trung gian bằng cách gọi phương thức

publish;

Phương thức process chứa các lệnh được thực

hiện trong luồng đồ họa để cập nhật dần giao diện.

● Trong chương trình ví dụ, ta không sử dụng các kết

quả trung gian nên không dùng publish và process.

Trang 14

Luồng công việc

đó nếu giá trị của các thuộc tính này thay đổi thì sẽ làm

phát siinh sự kiện thuộc kiểu PropertyChangeEvent

thức setProgress

Trang 15

class PrimeEnumerationTask extends SwingWorker<DefaultListModel, Integer> {

private int n ;

private DefaultListModel listModel ;

public PrimeEnumerationTask( int n) {

super ();

this n = n;

listModel = new DefaultListModel();

}

@Override

protected DefaultListModel doInBackground() throws IOException {

PrimeNumbers pn = new PrimeNumbers();

setProgress(0);

int k = 2;

while (k <= n && !isCancelled()) {

if (pn.isPrime(k)) {

listModel addElement(k);

} setProgress(100 * k / n );

k++;

}

return listModel ; }

Kết quả trung gian (từng số nguyên tố)

Không được cập nhật giao diện đồ họa ở đây!

Trang 16

class PrimeEnumerationTask extends SwingWorker<DefaultListModel, Integer> {

// more code goes here

@Override

protected void done() {

// update the UI in the EDT

okButton setEnabled( true );

primeList setModel( listModel );

}

}

Các lệnh trong done sẽ được chạy trong luồng đồ họa khi luồng công việc kết thúc

class EnumeratePrimeNumbersListener implements ActionListener {

@Override

public void actionPerformed(ActionEvent event) {

// some code

progressMonitor = new ProgressMonitor(

PrimeNumberFrame this , "Computing prime numbers " ,

"" , 0, 100);

progressMonitor setProgress(0);

task = new PrimeEnumerationTask(n);

Trang 17

class ProgressPropertyChangeListener implements PropertyChangeListener {

@Override

public void propertyChange(PropertyChangeEvent event) {

if (event.getPropertyName().equals( "progress" )) {

int progress = (Integer) event.getNewValue();

progressMonitor setProgress(progress);

progressMonitor setNote( "" + progress + "%" );

if ( progressMonitor isCanceled() || task isDone()) {

Toolkit.getDefaultToolkit().beep();

if ( progressMonitor isCanceled()) {

task cancel( true );

System.out.println( "Task canceled." );

} else {

System.out.println( "Task completed." );

}

okButton setEnabled( true );

}

} }

}

Cập nhật tiến trình thực hiện tác vụ

Bật lại nút Ok nếu tác vụ bị hủy giữa chừng hoặc đã thực hiện xong

Trang 18

Chương trình

Xem các tệp mã nguồn trong gói lecture8.primes4

– ​LookAndFeelLister.java

– PrimeNumberApp.java

– PrimeNumberFrame.java

– PrimeNumbers.java

– PrimeNumberIO.java

Trang 19

Tiếp theo

● Ta có thể tiếp tục cải tiến chương trình theo hướng

làm chương trình trực quan sinh động hơn:

– Tìm được số nguyên tố nào thì cập nhật dần kết

quả vào danh sách luôn, không đợi tìm hết mọi số mới cập nhật toàn bộ danh sách.

Gợi ý: Sử dụng các phương thức publish và process.

Trang 20

Tham khảo thêm

● Concurrency in Swing:

index.html

● How to use progress bars

progress.html

● How to write a property change listener:

tychangelistener.html

Ngày đăng: 30/01/2020, 08:01

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w