2013-04-21 19 views
1

我是新的擺動progarmming和即時通訊有一些困難與線程同步。Java搖擺畫錯誤的圖片由於延遲

我想迭代一個數組,並在每個索引處創建一個JPanel和一個JFrame,並且想在每個面板上繪製一張圖片。與存儲在數組中的值相關的圖片。 但是,所有的幀/面板只能保存最後一個數組條目的圖片。我認爲這是由於單獨的擺動線程(?),但我不知道如何改變它。 你能幫我嗎?

package help; 

import java.awt.Graphics; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class SwingSynchro{ 

private JPanel jPanel; 
private JFrame jFrame; 
int array[] = {1,2,3,4}; 
int current; 
private BufferedImage image1; 
private BufferedImage image2; 
private BufferedImage image3; 
private BufferedImage image4; 

public SwingSynchro(){ 

    //try{ 
    // image1 = ImageIO.read(new File("someFilePath1.png")); 
    // image2 = ImageIO.read(new File("someFilePath2.png")); 
    // image3 = ImageIO.read(new File("someFilePath3.png")); 
    // image4 = ImageIO.read(new File("someFilePath4.png")); 
    //} catch(IOException e){ 
    // e.printStackTrace(); 
    // System.out.println("wrong file path"); 
    //}// try catch 

    for(int i = 0 ; i < array.length ; i++){ 

     current = array[i]; 
      System.out.println("current Number: "+ current + " at array index:" +i); 

      jPanel = new JPanel(){ 
       private static final long serialVersionUID = 6859593162185621113L; 

       @Override 
       protected void paintComponent(Graphics g){ 
        super.paintComponent(g); 

        switch(current){ 
         case 1: 
          System.out.println("case 1"); 
          //g.drawImage(image1, 10, 10, getWidth() - 20, getHeight() - 20, this); 
          break; 
         case 2: 
          System.out.println("case 2"); 
          // g.drawImage(image2, 20, 20, getWidth() - 40, getHeight() - 40, this); 
          break; 
         case 3: 
          System.out.println("case 3"); 
          //g.drawImage(image3, 10, 10, getWidth() - 20, getHeight() - 20, this); 
          break; 
         case 4: 
          System.out.println("case 4"); 
          //g.drawImage(image4, 10, 10, getWidth() - 20, getHeight() - 20, this); 
          break; 
         default: 
          System.out.println("RELEASE THE KRAKEN!"); 
          break; 
        }// switch 
       }// paintComponent() 
      };// anonymous class(extends JPanel) 


     jFrame = new JFrame(String.valueOf(current)); 
     jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jFrame.setResizable(false); 
     jFrame.getContentPane().add(jPanel); 
     jFrame.setSize(200, 250); 
     jFrame.setLocation(i * 203, 0); 
     jFrame.setVisible(true); 
    } 
} 
} 

我註釋掉的照片,因爲控制檯輸出,你可以清楚地看到的drawImage方法獲得了整個for循環後調用。

編輯:它看起來像沒有其他線程,但在這種情況下,我不明白爲什麼圖紙(或病例陳述)有這種延遲。你能向我解釋爲什麼代碼不能照常執行嗎?

這裏是輸出:

current Number: 1 at array index:0 
current Number: 2 at array index:1 
current Number: 3 at array index:2 
current Number: 4 at array index:3 
case 4 
case 4 
case 4 
case 4 
+1

你說的是多線程,但我完全沒有看到代碼中的多線程。我錯過了明顯的東西嗎?如果是這樣,請展示給我。你的'Runnable'在哪裏?你在哪裏創建這個所謂的後臺線程,你叫'start()'? – 2013-04-21 00:42:40

+0

我只是假設有異步線程,因爲這是我對該行爲的唯一補救。 – BraveHeart 2013-04-21 01:00:15

+0

你的假設是不正確的。當你直接或間接地創建後臺線程時,你將擁有後臺線程,正如我上面提到的,我沒有看到你這樣做的地方。 – 2013-04-21 01:04:39

回答

2

而不是實例化JPanel作爲一個匿名類,您可以使它成爲一個內部類,並使用字段來保存您的current變量的值。

private static class CustomJPanel extends JPanel { 
    private static final long serialVersionUID = 6859593162185621113L; 
    private final int current; 

    private CustomJPanel(int current) { 
     this.current = current; 
    } 

    @Override 
    protected void paintComponent(Graphics g){ 
     super.paintComponent(g); 

     switch(current){ 
      case 1: 
       System.out.println("case 1"); 
       //g.drawImage(image1, 10, 10, getWidth() - 20, getHeight() - 20, this); 
       break; 
      case 2: 
       System.out.println("case 2"); 
       // g.drawImage(image2, 20, 20, getWidth() - 40, getHeight() - 40, this); 
       break; 
      case 3: 
       System.out.println("case 3"); 
       //g.drawImage(image3, 10, 10, getWidth() - 20, getHeight() - 20, this); 
       break; 
      case 4: 
       System.out.println("case 4"); 
       //g.drawImage(image4, 10, 10, getWidth() - 20, getHeight() - 20, this); 
       break; 
      default: 
       System.out.println("RELEASE THE KRAKEN!"); 
       break; 
     }// switch 
    }// paintComponent() 
} 

,然後就實例作爲

jPanel = new CustomJPanel(current); 

這樣,你要確保它已經通過了JPanel中被實例化時current變量所具有的值。

+0

這工作,謝謝!但我不知道這是否是好的編碼。 – BraveHeart 2013-04-21 01:10:34

+0

我更喜歡將內部類寫入匿名類,只要它們長於5行。至於構造函數參數,我相信這是正確的(也是線程安全的),因爲在實例化JPanel時確實需要'current'變量的值。請考慮接受答案。 – 2013-04-21 01:13:44

+0

@Enum:Zoltan的編碼沒有問題,事實上這經常被普遍和有效地使用(如他所示)。 1+。 – 2013-04-21 01:15:56

2

Swing是單線程的。如果您想實時查看GUI更新,請使用Swing Timer