2015-04-05 92 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