I want to learn threads in swing. I found this SwingWorker class and I've already written simple code to move some images. But i still have a problem. There's only one image that is repainted. When main thread is working with its image, second one is calculating position of image and it's supposed to repaint. Here's code of Image class (resonsible for changing integer position and drawing):
>>> old = 'ABCDEF'
>>> new = 'ABCDGHI'
>>> set(new) - set(old)
{'H', 'I', 'G'}
>>> set(old) - set(new)
{'F', 'E'}
Code of WalkingThread which extends Image, adding function running() which is handled by SwingWorker. Function is responsible to move 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);
}
}
Another code of main frame which extend JFrame and implements KeyListener:
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();
}
}
And main class, handling events:
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();
}
}
I can't find my mistake.
答案 0 :(得分:0)
Book Title | Book Author | Book Dimension | Book ID
Title 1 | Author 1 | Height:#cm;Width#cm | 001
Title 2 | Author 2 | Height:#cm;Width#cm | 002
is the only worker which is actually causing any kind of updates to occur to it's image. This solution isn't going to scale well, the more images you add, the slower it will become. Instead of using the "walking thread", you should have a single thread which updates all the entities, schedules a repaint and generates a pause between frames.
Beware though, Swing is not thread safe and you should never update the UI out side of the context of the Event Dispatching Thread, this is actually what the MosterThread
is suppose to help fix, by providing SwingWorker
and process
methods which allow you to send data from the background thread to the EDT
Take a look at Concurrency in Swing for more details