[英]Repaint a JPanel
I would like to repaint my jPanel I've a App class who handle the screen displaying in this JFrame I add a Board JPanel object who handle all the JPanel. 我想重绘我的jPanel,我有一个App类负责处理此JFrame中显示的屏幕,我添加了一个处理所有JPanel的Board JPanel对象。 In the Board class I had
在董事会班上
ex = new Explosion(10, 10);
new Thread(ex).start();
And in my Explosion class I have a constructor who crop my sprite file, an overwriting of paint() and : 在Explosion类中,我有一个构造函数,该构造函数裁剪了我的sprite文件,覆盖了paint()和:
public void run()
{
while(cursor < (rows*cols))
{
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(cursor);
cursor++;
}
}
The loop is working fine but I have no repaint in my screen , only the first image is display. 循环工作正常,但屏幕上没有重画,仅显示第一个图像。
What can I do to refresh ? 我该怎么做才能刷新?
Thanks 谢谢
Edit : Here is my code : 编辑:这是我的代码:
public class Explosion extends JPanel implements Runnable{
private BufferedImage img;
final int width = 320;
final int height = 320;
final int rows = 5;
final int cols = 5;
private int x,y;
private int cursor;
BufferedImage[] sprites = new BufferedImage[rows * cols];
public Explosion(int x, int y)
{
this.x = x;
this.y = y;
try {
try {
this.img = ImageIO.read(new File((this.getClass().getResource("files/explosion2.png")).toURI()));
} catch (URISyntaxException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
cursor = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
sprites[(i * cols) + j] = img.getSubimage(
i * (width/rows),
j * (height/cols),
width/rows,
height/cols
);
}
}
}
public void run()
{
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
cursor++;
repaint();
}
};
while(cursor < (rows*cols))
{
new Timer(50, taskPerformer).start();
if (cursor==(rows*cols)-1)
cursor=0;
}
}
public void paintComponent(Graphics g){
System.out.println("paintComponent");
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(sprites[cursor], x, y, this);
g.dispose();
}
/*public void paint(Graphics g) {
super.paint(g);
System.out.println("paint");
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(sprites[cursor], x, y, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}*/
}
public class Main extends JFrame{
public Main()
{
Board board = new Board();
add(board);
setTitle("Explosion");
setSize(500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
public class Board extends JPanel{
Explosion ex;
public Board()
{
setDoubleBuffered(true);
ex = new Explosion(10,10);
new Thread(ex).start();
}
public void paint(Graphics g) {
ex.paintComponent(g);
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
}
@StanislavL (I can't comment yet): No, you don't have to call repaint()
in the EDT: @StanislavL(我无法评论):不,您不必在EDT中调用
repaint()
:
The following JComponent methods are safe to call from any thread:
repaint()
,revalidate()
, andinvalidate()
.可以从任何线程安全调用以下JComponent方法:
repaint()
,revalidate()
和invalidate()
。 Therepaint()
andrevalidate()
methods queue requests for the event-dispatching thread to callpaint()
andvalidate()
, respectively.repaint()
和revalidate()
方法将事件调度线程的请求排队,以分别调用paint()
和validate()
。 Theinvalidate()
method just marks a component and all of its direct ancestors as requiring validation.invalidate()
方法仅将组件及其所有直接祖先标记为需要验证。
Source: http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#exceptions 来源: http : //java.sun.com/products/jfc/tsc/articles/threads/threads1.html#exceptions
Is cursor
declared as volatile
? cursor
是否声明为volatile
? If not, the EDT may not see the changes the thread made to cursor
. 如果不是,则EDT可能看不到线程对
cursor
所做的更改。 Therefore, always the first image is painted. 因此,始终绘制第一张图像。
paint
, instead override paintComponent
paint
,而是覆盖paintComponent
Thread.sleep
, instead use a utility class, such as javax.swing.Timer
to execute a particular action at a specified interval. Thread.sleep
,而要使用实用程序类,例如javax.swing.Timer
,以指定的时间间隔执行特定的操作。 This will ensure that all changes are done on the EDT and that the waiting occurs in a background thread. Note that without compilable code, it's hard to tell what the real problem is; 注意,没有可编译的代码,很难说出真正的问题是什么; this is all guesswork.
这都是猜测。
Repaint must be called in EDT. 必须在EDT中调用重绘。
Use SwingUtilities.invokeAndWait() or invokeLater() to call repaint. 使用SwingUtilities.invokeAndWait()或invokeLater()调用重绘。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.