[英]Why doesn't AWT/Swing repaint automatically when adding a component to a container?
[英]Awt/Swing - Frame doesn't repaint during move process
我正在嘗試創建一個帶有一些用於“堆棧”的圖形的示例。 我想Wagons
在一個軌道這是'stacks'為“再生俠”而動。 移動過程由“ Wagon”本身完成。 我已經嘗試過為Wagon引用我的“ Frame”(稱為“ Window”)以在每個循環中對其進行重新繪制,但是直到它停止時它仍然不顯示。
車皮:
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Window extends JFrame {
private Stack stack1 = new Stack(1);
public Window() {
setSize(800, 400);
setResizable(false);
setLayout(null); //Not perfect, but it works for those little things
setVisible(true);
createTracks(); //Tracksgraphic made out of gray rects
}
public void addWagon(Wagon wagon) { //Is called when adding a Wagon
this.add(wagon);
stack1.addWagon(wagon);
}
public static void main(String[] args) { //main
new Window();
}
}
堆:
public class Stack {
private int gleis; //gleis = german for track
private Wagon first = null;
public Stack(int g) {
gleis = g;
}
public void addWagon(Wagon wagon) {
if (first != null) {
wagon.setNext(first);
}
first = wagon;
first.moveRight(gleis);
}
public void removeWagon(int id, Stack nextStack) {
Wagon speicherFirst = first;
first.moveLeft(null);
first = first.getNext();
while (speicherFirst.getID() != id) {
speicherFirst.setNext(first);
first.moveLeft(speicherFirst);
speicherFirst = first;
first = first.getNext();
}
nextStack.addWagon(speicherFirst);
if (speicherFirst.getNext() != null) {
speicherFirst = speicherFirst.getNext();
while (speicherFirst!= null) {
speicherFirst.moveRight(gleis);
speicherFirst = speicherFirst.getNext();
}
}
}
public boolean hasID(int id) {
return first.isID(id);
}
}
車皮:
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class Wagon extends JPanel { //Entspricht einem Canvas aus .awt
private Wagon next;
private int id;
public Wagon(int i) {
id = i;
setSize(50, 20);
Random r = new Random();
setBackground(new Color(r.nextFloat(), r.nextFloat(), r.nextFloat()));
setVisible(true);
}
public boolean isID(int i) {
if (id == i) {
return true;
} else if (next == null) {
return false;
} else {
return next.isID(i);
}
}
public void setNext(Wagon n) {
next = n;
}
public void moveRight(int gleis) {
setLocation(getX(), gleis * 100);
if (next != null) {
while (next.getX() - getX() < 70) {
next.moveRight(gleis);
move(3);
}
} else {
while (getX() < 700) {
move(3);
}
}
}
public Wagon getNext() {
return next;
}
public int getID() {
return id;
}
public void moveLeft(Wagon previous) {
if (previous == null) {
while (getX() > 50) {
move(-3);
}
} else {
while (getX() - previous.getX() > 50) {
move(-3);
}
}
}
public void move(int dir) {
this.setLocation(getX() + dir, getY());
try {
Thread.sleep(20);
} catch (InterruptedException e) {}
}
}
直到它停止它仍然不顯示。
您的代碼在事件分發線程(EDT)上執行,該線程負責處理GUI事件和重新繪制GUI。 Thread.sleep()防止GUI重新繪制自身,直到while / loop完成執行,因此您只能在最后看到繪制。 閱讀Swing 並發教程中的有關更多信息的部分。
解決方案是使用Swing Timer提供動畫,而不是Thread.sleep()。
看來您實際上沒有replaint();
在代碼中的任何地方調用。 我將在moveLeft()
和moveRight()
命令中都使用它。
另一件事,您正在使用JPanels作為貨車。 我不會這樣做,這會占用更多資源並且是不明智的做法。 除非有特殊原因,否則我將使用基本的sprite圖像,並將其加載到int[]
數組,然后使用BufferedImage將該數組繪制到該屏幕上,而不用花X個JPanel運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.