我想学习 swing 中的线程。我找到了这个 SwingWorker 类,并且我已经编写了简单的代码来移动一些图像。但我仍然有一个问题。只有一张图像被重新绘制。当主线程处理其图像时,第二个线程正在计算图像的位置,并且应该重新绘制。这是Image类的代码(负责更改整数位置和绘图):
public class Image extends JComponent
{
private BufferedImage image;
protected int x_location, y_location;
protected int window_size;
protected int speed;
void move_Up()
{
this.y_location -= speed;
}
void move_Down()
{
this.y_location += speed;
}
void move_Left()
{
this.x_location -= speed;
}
void move_Right()
{
this.x_location += speed;
}
public Image(String directory, int size)
{
File file = new File(directory);
try
{
image = ImageIO.read(file);
}
catch (IOException e)
{
e.printStackTrace();
}
x_location = 50;
y_location = 50;
speed = 1;
window_size = size;
setPreferredSize(new Dimension(50,50));
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D graphic = (Graphics2D) g;
graphic.drawImage(image, x_location, y_location, this);
}
}
WalkingThread 的代码扩展了 Image,添加了由 SwingWorker 处理的函数 running()。函数负责移动图像:
public class WalkingThread extends Image
{
boolean directory;
public WalkingThread(String image, int size)
{
super(image, size);
}
void running()
{
System.out.println("Repainting");
this.repaint();
if( this.y_location == 0) this.directory = true;
else if( this.y_location+50 == this.window_size) this.directory = false;
if( this.directory == true ) this.move_Down();
else if( this.directory == false ) this.move_Up();
System.out.println(this.y_location+" "+ this.x_location);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void start()
{
System.out.println("I'm in start");
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>()
{
protected Void doInBackground() throws Exception
{
System.out.println("I'm in doInBackground");
while(true)
{
running();
}
}
};
worker.execute();
}
}
主框架的另一段代码,扩展了JFrame并实现了KeyListener:
public class Window extends JFrame implements KeyListener{
Image animal;
WalkingThread MonsterThread;
int window_Size;
public Window()
{
super("Walking Threads");
window_Size = 400;
setSize(window_Size, window_Size);
setLocation(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
addKeyListener(this);
MonsterThread = new WalkingThread("kulka.png", window_Size);
MonsterThread.start();
add(MonsterThread);
animal = new Image("kulka.png", window_Size);
add(animal);
}
public void keyPressed(KeyEvent key)
{
int pressed = key.getKeyCode();
if( pressed == KeyEvent.VK_W)
animal.move_Up();
else if( pressed == KeyEvent.VK_S)
animal.move_Down();
else if( pressed == KeyEvent.VK_A)
animal.move_Left();
else if( pressed == KeyEvent.VK_D)
animal.move_Right();
animal.repaint();
}
}
和主类,处理事件:
public class Main {
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Window();
}
});
}}
我找不到我的错误。
最佳答案
MosterThread
是唯一真正导致其图像发生任何类型更新的工作线程。该解决方案无法很好地扩展,添加的图像越多,速度就越慢。您应该使用一个线程来更新所有实体、安排重绘并在帧之间生成暂停,而不是使用“行走线程”。
但请注意,Swing 不是线程安全的,您永远不应该在事件调度线程的上下文之外更新 UI,这实际上是 SwingWorker
应该帮助解决的问题,通过提供 process
和 publish
方法,允许您将数据从后台线程发送到 EDT
看看Concurrency in Swing了解更多详情
关于java - 如何使用 Swingworker 重新绘制多个图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30202623/