2015-04-05 36 views
2

我正在使用多個BufferedImages。我現在用的是JPanel的塗料功能借鑑了JPanel的currentImg:JPanel不重畫

@Override 
public void paint(Graphics g) { 
    g.drawImage(currentImg, 0, 0, null); 
} 

currentImg使用,所以我可以很容易地切換圖像,它在一開始等於normalImg。 redImg是一個與normalImg不同的BufferedImage。 現在我想繪製redImg半秒鐘,然後再次normalImg。

currentImg = redImg; 
repaint(); 
Thread.sleep(1000); 
currentImg = normalImg; 
repaint(); 

但是這段代碼什麼都不做,JPanel沒有重新繪製。此代碼雖然工作:

currentImg = redImg; 
repaint(); 
JOptionPane.showMessageDialog(this,"test"); 
Thread.sleep(1000); 
JOptionPane.showMessageDialog(this,"test"); 
currentImg = normalImg; 
repaint(); 

但我不想顯示消息對話框只是爲了重新正確重繪它。 感謝您的幫助:)

回答

5
  1. 避免重寫paint,尤其是頂層容器,使用基於JComponent部件和覆蓋其paintComponent方法。看看Painting in AWT and SwingPerforming Custom Painting爲更多細節Swing中氣喘吁吁
  2. 始終調用什麼都畫法你重寫
  3. 不要使用Thread.sleep從事件指派線程的上下文中super.paintXxx,這將阻止它從處理來自EventQueue的新事件,包括重繪事件。
  4. 不要從事件分派線程的上下文之外修改UI。

看看Concurrency in Swing的詳細信息和How to use Swing Timers的可能解決方案

而一個example

+0

1.我不知道爲什麼我應該這樣做,但'paintComonent'做同樣對我來說,所以我改變它 2.沒有覆蓋油漆 3.現在我用一個鞦韆定時器,謝謝 我不明白你的意思是4. 但現在它的作品。非常感謝你! – kaesaecracker 2015-04-05 22:35:24

+0

@kaesaecracker嘗試在面板上添加一個組件,覆蓋'paint'。然後切換到'paintComponent',不同的應該是明顯的。 – Obicere 2015-04-05 22:39:12

+0

@Obicere我不需要JPanel內部的任何組件,實際上整個應用程序只使用一個JFrame和一個JPanel,而不是更多:) – kaesaecracker 2015-04-05 22:47:55

4

通過在paint方法和Swing事件線程中調用Thread.sleep(...)來凍結整個應用程序。不要這樣做。取而代之的是使用Swing Timer,並從Timer中交換JLabel的圖標。

例如:

enter image description here

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

public class SwapImages extends JPanel { 
    private static final int TIMER_DELAY = 200; 
    private static final String SPRITE_PATH = "http://th02.deviantart.net/" 
     + "fs70/PRE/i/2011/169/0/8/blue_player_sprite_sheet_by_resetado-d3j7zba.png"; 
    public static final int SPRITE_ROWS = 6; 
    public static final int SPRITE_COLS = 6; 
    public static final int SPRITE_CELLS = 35; 

    private JLabel label = new JLabel(); 
    private List<ImageIcon> iconList = new ArrayList<ImageIcon>(); 
    private int iconIndex = 0; 

    public SwapImages() throws IOException { 
     URL imgUrl = new URL(SPRITE_PATH); 
     BufferedImage mainImage = ImageIO.read(imgUrl); 

     for (int i = 0; i < SPRITE_CELLS; i++) { 
     int row = i/SPRITE_COLS; 
     int col = i % SPRITE_COLS; 
     int x = (int) (((double) mainImage.getWidth() * col)/SPRITE_COLS); 
     int y = (int) ((double) (mainImage.getHeight() * row)/SPRITE_ROWS); 
     int w = (int) ((double) mainImage.getWidth()/SPRITE_COLS); 
     int h = (int) ((double) mainImage.getHeight()/SPRITE_ROWS); 
     BufferedImage img = mainImage.getSubimage(x, y, w, h); 
     ImageIcon icon = new ImageIcon(img); 
     iconList.add(icon); 
     } 
     add(label); 
     label.setIcon(iconList.get(iconIndex)); 
     new Timer(TIMER_DELAY, new TimerListener()).start(); 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent arg0) { 
     iconIndex++; 
     iconIndex %= iconList.size(); 
     label.setIcon(iconList.get(iconIndex)); 
     } 
    } 

    private static void createAndShowGui() { 
     SwapImages mainPanel = null; 
     try { 
     mainPanel = new SwapImages(); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     System.exit(-1); 
     } 

     JFrame frame = new JFrame("SwapImages"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 
+0

我不改變一個JLabel的ImageIcon的,但數據的BufferedImage畫上一個JPanel – kaesaecracker 2015-04-05 22:40:08

+1

@kaesaecracker :我明白了,但如果你只是在交換圖像,有時用圖像圖標更容易,尤其是在做動畫的時候。 – 2015-04-05 22:40:50

+0

@HovercaftFullOfEels我看到這可能是有用的,但我需要首先創建這些ImageIcons,我不知道應用程序具有的分辨率 – kaesaecracker 2015-04-05 22:51:01