I saw a Topic about multi thread here : Multi-threading with Swing
So I do as the answer https://stackoverflow.com/a/33908340/11445086
I implement like codes below but there's not anything movement here. I know the problem is about my doInBackGround and process implementation but I don't know how to do.I'm really new with Swing Builder so sorry if the question's silly. The program just makes many circles moving in the Panel. And each circle is a Thread that be made by Swing Worker.
these're my classes:
Robot class :
package com.mycompany.test;
import java.awt.Color;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;
public class Robot extends SwingWorker< Void ,Integer> {
public int x;
public int y;
public Color color;
public final int speed = 10;
Robot(int x , int y , Color color)
{
this.x = x;
this.y = y;
this.color = color;
}
public void move_90()
{
this.y += speed;
}
public void move_270()
{
this.y -= speed;
}
public void move_180()
{
this.x += speed;
}
public void move_0()
{
this.x += speed;
}
public void move_45()
{
this.x += speed;
this.y += speed;
}
public void move_135()
{
this.x -= speed;
this.y += speed;
}
public void move_225()
{
this.x -= speed;
this.y -= speed;
}
public void move_315()
{
this.x += speed;
this.y -= speed;
}
public void move()
{
Random temp = new Random();
int rand = temp.nextInt(8);
switch(rand)
{
case 1: move_0();
break;
case 2: move_135();
break;
case 3: move_180();
break;
case 4: move_225();
break;
case 5: move_270();
break;
case 6: move_315();
break;
case 7: move_45();
break;
case 8: move_90();
break;
}
}
@Override
protected void process(List<Integer> chunks) {
while(true)
{
move();
if(x < 40) x = 40;
if(x > PlayField.width - 40) x = (PlayField.width - 40);
if(y < 40) y = 40;
if(y > PlayField.height - 40) y = (PlayField.height - 40);
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Robot.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
protected Void doInBackground() throws Exception {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
RobotModel class :
package com.mycompany.test;
import java.awt.Color;
import java.util.LinkedList;
public class RobotModel {
public static final int MAX = 8;
public LinkedList<Robot> model = new LinkedList<Robot>();
public void add_New_Robot()
{
Robot temp = new Robot( 40 , 40 , Color.BLUE);
model.addFirst(temp);
}
}
PlayField class :
package com.mycompany.test;
import java.awt.Color;
public class PlayField {
public static int width;
public static int height;
public static Color fill_Color;
PlayField(int width , int height , Color fill_Color)
{
this.width = width;
this.height = height;
this.fill_Color = fill_Color;
}
}
RobotWorld class :
package com.mycompany.test;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class RobotWorld extends JPanel {
public RobotModel robot_Model;
public RobotWorld(RobotModel robot_Model) {
super();
this.robot_Model = robot_Model;
this.setSize(PlayField.width , PlayField.height);
this.setVisible(true);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphic = (Graphics2D)g;
graphic.setBackground(PlayField.fill_Color);
for(Robot x : robot_Model.model )
{
graphic.setColor(x.color);
graphic.drawOval(x.x, x.y, 40, 40);
}
}
}
And finally , GameMain class :
package com.mycompany.test;
import java.awt.Color;
import javax.swing.JFrame;
public class GameMain extends JFrame {
RobotModel a;
PlayField field;
public void Game_Start()
{
Robot robot = new Robot(100, 100, Color.RED);
a = new RobotModel();
RobotWorld world = new RobotWorld(a);
world.robot_Model.add_New_Robot();
this.setSize(field.width , field.height);
this.add(world);
this.setVisible(true);
world.repaint();
}
// public void gameUpdate(Robot a , PlayField field)
// {
// a.move();
// if(a.x < 40) a.x = 40;
// if(a.x > field.width - 40) a.x = (field.width - 40);
// if(a.y < 40) a.y = 40;
// if(a.y > field.height - 40) a.y = (field.height - 40);
// }
public void gameUpdate(){
Thread gameThread = new Thread(){
public void run(){
while(true){
//execute one time step for the game
// gameUpdate(a , field);
//refresh screen
repaint();
//give other threads time
try{
Thread.sleep(5);
}catch(InterruptedException e){
// e.printStackTrace();
}
}
}
};
gameThread.start();
}
public static void main(String args[])
{
GameMain main = new GameMain();
main.Game_Start();
main.gameUpdate();
}
}
The problems are multiple, mostly to do with a lack of understand over how SwingWorker
actually works.
Remember, more threads doesn't always more more work. The more threads you have, the harder the system will have to work. Sometimes, less is more ;)
SwingWorker
is not well suited to this task. It will only allow a maximum of 10 workers to execute, for the WHOLE app and, unless you're synchronising your updates with the Event Dispatching Thread properly, you'd not be gaining any benefit from it.
A generally simpler solution would be to make use of a Swing Timer
instead. This will ensure your updates are carried out within the EDT without the risk of dirty read/writes or blocking the EDT.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
PlayField playField = new PlayField(200, 200, Color.DARK_GRAY);
RobotModel model = new RobotModel();
model.createNewRobot();
RobotWorld world = new RobotWorld(playField, model);
world.start();
frame.add(world);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RobotModel {
public static final int MAX = 8;
public LinkedList<Robot> bots = new LinkedList<Robot>();
public void createNewRobot() {
Robot temp = new Robot(40, 40, Color.BLUE);
bots.addFirst(temp);
}
}
public class PlayField {
public int width;
public int height;
public Color fill_Color;
PlayField(int width, int height, Color fill_Color) {
this.width = width;
this.height = height;
this.fill_Color = fill_Color;
}
}
public class RobotWorld extends JPanel {
public RobotModel model;
private PlayField playField;
private Timer timer;
public RobotWorld(PlayField playField, RobotModel robot_Model) {
super();
this.model = robot_Model;
this.playField = playField;
setBackground(playField.fill_Color);
timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
for (Robot bot : model.bots) {
bot.move(bounds);
}
repaint();
}
});
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
@Override
public Dimension getPreferredSize() {
return playField == null ? super.getPreferredSize() : new Dimension(playField.width, playField.height);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Robot bot : model.bots) {
Graphics2D graphic = (Graphics2D) g.create();
bot.paint(graphic);
graphic.dispose();
}
}
}
public class Robot {
public int x;
public int y;
public Color color;
public final int speed = 10;
public int size = 40;
Robot(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public void paint(Graphics2D g2d) {
g2d.setColor(color);
g2d.fillRect(x, y, size, size);
}
public void move_90() {
this.y += speed;
}
public void move_270() {
this.y -= speed;
}
public void move_180() {
this.x += speed;
}
public void move_0() {
this.x += speed;
}
public void move_45() {
this.x += speed;
this.y += speed;
}
public void move_135() {
this.x -= speed;
this.y += speed;
}
public void move_225() {
this.x -= speed;
this.y -= speed;
}
public void move_315() {
this.x += speed;
this.y -= speed;
}
public void move(Rectangle bounds) {
Random temp = new Random();
int rand = temp.nextInt(8);
switch (rand) {
case 1:
move_0();
break;
case 2:
move_135();
break;
case 3:
move_180();
break;
case 4:
move_225();
break;
case 5:
move_270();
break;
case 6:
move_315();
break;
case 7:
move_45();
break;
case 8:
move_90();
break;
}
if (x < bounds.x) {
x = bounds.x;
} else if (x + size > bounds.x + bounds.width) {
x = bounds.x + bounds.width - size;
}
if (y < bounds.y) {
y = bounds.y;
} else if (y + size > bounds.y + bounds.height) {
y = bounds.y + bounds.height - size;
}
}
}
}
See How to Use Swing Timers for more details
If you're hell bent on using a SwingWorker
, then you should take the time to read through Worker Threads and SwingWorker