2011-09-28 6 views
7

Tôi đang làm cho bộ nhớ trò chơi, khi bạn chọn hai thẻ và nếu họ phù hợp với bạn có thể giữ chúng, nếu không bạn quay trở lại. Nếu sau đó bạn nhớ thẻ bạn đã chọn, bạn có thể mạo hiểm một dự đoán tốt hơn về hai thẻ tiếp theo.Làm cách nào để gọi một bản cập nhật tức thì cho GUI Java? (xung đột với Thread.sleep())

Sự cố tôi liên quan đến phương pháp repaint() không được sơn lại ngay lập tức.

Khi tôi lật thẻ thứ hai, bất kể kết quả, tôi muốn hiển thị cả hai thẻ lật bên phải trước khi loại bỏ chúng hoặc lật chúng trở lại. Tôi làm điều này bằng cách gọi số sleep().

Tất nhiên nếu tôi repaint() thẻ lật chúng sang bên phải, đợi một giây, sau đó lại repaint() dựa trên giá trị của chúng, Java nhỏ hữu ích sẽ chỉ vẽ lại một lần (tôi nhớ C!).

Về cơ bản tôi muốn ép buộc cập nhật trước sleep(). Tôi đã đọc một số chủ đề khác về cơ bản nói cách tốt nhất là tạo hai luồng để giữ logic và đồ họa riêng biệt, và sau đó bạn có thể sleep() logic của mình và cập nhật GUI, nhưng tôi đang học kỳ đầu tiên của CS năm đầu tiên khóa học ở trường trung học, và tôi muốn giữ nó ở trình độ của khóa học (mặc dù tôi đã dành khá nhiều thời gian cho việc phát triển và viết mã mùa hè trong C).

Vì tôi biết những người hữu ích trên StackOverflow thích đọc mã, đây là một phần của chương trình tôi đang đề cập bên dưới. Lớp HitArea là đối tượng Thẻ và mảng cards[] chứa số tiền là HitArea. (Tôi chưa đổi tên lớp HitArea). activeCard1activeCard2HitArea trường hợp tôi sử dụng để theo dõi hai lựa chọn của người dùng và hàm tạo trống được đặt trước là "vô hình" HitArea, mặc dù tôi sẽ thay đổi thành null sau này. Cuối cùng, cards.flip() sẽ chuyển đổi một số toggle boolean xác định xem thẻ có ở bên phải hay không.

public void respond(HitArea choice) 
{ 
    if(choice.inGame) 
    { 
     if(activeCard1.value == 0 && activeCard1.value == 0) 
      activeCard1 = choice; 
     else if((!(activeCard1.value == 0) && activeCard2.value == 0) && (activeCard1.id != choice.id)) 
     { 
      activeCard2 = choice; 
      check(); 
     } 

    } 
} 
public void check() 
{ 
    update(); 
    pause(250); 
    if(activeCard2.value == activeCard1.value) 
    { 
     score += 2; 
     activeCard1.inGame = false; 
     activeCard2.inGame = false; 
    } 
    activeCard1.flip(); 
    activeCard2.flip(); 
    activeCard1 = new HitArea(); 
    activeCard2 = new HitArea(); 
} 
public void pause(int milliseconds) 
{ 
    try{ 
     Thread.currentThread().sleep(milliseconds); 
    } 
    catch(InterruptedException e){ 
     System.out.println("Exception: " + e); 
    } 
} 

public void mousePressed(MouseEvent e) 
{ 
    int x = e.getX(); 
    int y = e.getY(); 

    for (int i = 0; i < cardNum; i++) 
     if(cards[i].boundsCheck(x, y)) 
     { 
      repaint(); 
      cards[i].flip(); 
      respond(cards[i]); 
     } 
} 

Tôi không nghi ngờ có một số vấn đề trong mã của mình, vì vậy vui lòng chỉ ra chúng. Tôi nghĩ rằng cấu trúc cơ bản của tôi là ổn, và tôi không muốn tạo ra nhiều chủ đề cho dự án này (hãy nhớ, đó là cơ bản!).

Trả lời

14

Đừng gọi Thread.sleep (...) trên chủ đề Swing chính, EDT. Bao giờ. Thay vào đó sử dụng một Swing Timer.

Cân nhắc sử dụng JLabels để hiển thị hình ảnh của bạn và sau đó bạn có thể "lật" thẻ của mình bằng cách hoán đổi đơn giản với ImageIcons. Khi thẻ thứ hai bị lật, nếu không khớp, bắt đầu một Swing Timer không lặp lại với độ trễ cho xxxx ms, và trong phương thức actionCommand của ActionListener của Timer, nó sẽ hoàn nguyên cả JLabel về ImageIcon mặc định.

Các javax.swing.Timer hướng dẫn có thể được tìm thấy ở đây: How to use Swing Timers

Edit:
Về nhận xét của bạn về việc sử dụng g.drawString: nó thậm chí còn dễ dàng hơn bây giờ vì tất cả các bạn phải làm là trao đổi ra của bạn Văn bản của JLabel. Nhưng sau đó nếu bạn quyết định nâng cấp chương trình để hiển thị hình ảnh, bạn đã có tất cả các thiết lập để làm điều này.

Chỉnh sửa 2:
Về câu hỏi của bạn về việc tạo lớp ActionListener mới: Tôi muốn sử dụng lớp bên trong ẩn danh cho việc này. Ví dụ:

int delayTime = 2 * 1000; 
    javax.swing.Timer myTimer = new Timer(delayTime, new ActionListener() { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // TODO: put in the code you want called in xxx mSecs. 
    } 
    }); 
    myTimer.setRepeats(false); 
    myTimer.start(); 
+3

Tôi sẽ in đậm và in nghiêng "Bao giờ". :) – fireshadow52

+0

Tôi chỉ hiển thị một số văn bản g.drawString (...), không có hình ảnh. Điều tương tự có áp dụng không? –

+0

Cảm ơn và đã hoàn thành. :) –