У вас есть две разные ссылки на ваш мяч.
У вас есть ссылка на один Ball
, называемый ball
и List
мячей. Ваши методы update
и paint
ссылаются только на одиночный ball
Ball
, похоже, не имеют метода start
(который я вижу), поэтому этот параметр balls.get(count-1).start();
t смысл ...
Обновлено
ball
start
в конструкторе update
в BouncingBalls
должен прокручивать список balls
, вызывая move
на каждом шаре в списке ... paintComponent
DrawCanvas
нуждается в доступе и должен использовать список balls
. Это может быть лучше достижимо через интерфейс модели Ball
с параметрами, поскольку он дает каждому шару одинаковые свойства, особенно когда вы присваиваете ему случайные значения, когда вы его каким-либо образом создаете ... Ball
не имеет (или нуждается) метод start
[/g0]
public class BouncingBalls extends JPanel implements MouseListener {
// private Ball ball;
protected List<Ball> balls = new ArrayList<Ball>(20);
private Container container;
private DrawCanvas canvas;
private int canvasWidth;
private int canvasHeight;
public static final int UPDATE_RATE = 30;
int x = random(480);
int y = random(480);
int speedX = random(30);
int speedY = random(30);
int radius = random(20);
int red = random(255);
int green = random(255);
int blue = random(255);
int count = 0;
public static int random(int maxRange) {
return (int) Math.round((Math.random() * maxRange));
}
public BouncingBalls(int width, int height) {
canvasWidth = width;
canvasHeight = height;
// ball = new Ball(x, y, speedX, speedY, radius, red, green, blue);
container = new Container();
canvas = new DrawCanvas();
this.setLayout(new BorderLayout());
this.add(canvas, BorderLayout.CENTER);
this.addMouseListener(this);
start();
}
public void start() {
Thread t = new Thread() {
public void run() {
while (true) {
update();
repaint();
try {
Thread.sleep(1000 / UPDATE_RATE);
} catch (InterruptedException e) {
}
}
}
};
t.start();
}
public void update() {
for (Ball ball : balls) {
ball.move(container);
}
}
class DrawCanvas extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
container.draw(g);
for (Ball ball : balls) {
ball.draw(g);
}
// ball.draw(g);
}
public Dimension getPreferredSize() {
return (new Dimension(canvasWidth, canvasHeight));
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("Bouncing Balls");
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
f.setContentPane(new BouncingBalls(500, 500));
f.pack();
f.setVisible(true);
}
});
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
count++;
balls.add(new Ball());
// balls.add(new Ball(x, y, speedX, speedY, radius, red, green, blue));
// balls.get(count - 1).start();
// start();
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
public static class Ball {
public int random(int maxRange) {
return (int) Math.round(Math.random() * maxRange);
}
int x = random(480);
int y = random(480);
int speedX = random(30);
int speedY = random(30);
int radius = random(20);
int red = random(255);
int green = random(255);
int blue = random(255);
int i = 0;
public Ball() { //int x, int y, int speedX, int speedY, int radius, int red, int green, int blue) {
// this.x = x;
// this.y = y;
// this.speedX = speedX;
// this.speedY = speedY;
// this.radius = radius;
// this.red = red;
// this.green = green;
// this.blue = blue;
}
public void draw(Graphics g) {
g.setColor(new Color(red, green, blue));
g.fillOval((int) (x - radius), (int) (y - radius), (int) (2 * radius), (int) (2 * radius));
}
public void move(Container container) {
x += speedX;
y += speedY;
if (x - radius < 0) {
speedX = -speedX;
x = radius;
} else if (x + radius > 500) {
speedX = -speedX;
x = 500 - radius;
}
if (y - radius < 0) {
speedY = -speedY;
y = radius;
} else if (y + radius > 500) {
speedY = -speedY;
y = 500 - radius;
}
}
}
public static class Container {
private static final int HEIGHT = 500;
private static final int WIDTH = 500;
private static final Color COLOR = Color.WHITE;
public void draw(Graphics g) {
g.setColor(COLOR);
g.fillRect(0, 0, WIDTH, HEIGHT);
}
}
}
Обновлено
Как отмечают комментаторы, ArrayList
не является потокобезопасным, не рекомендуется иметь несколько потоков, пытающихся получить к нему доступ одновременно. Хотя добавление немного безопаснее, чем удаление, это по-прежнему плохая практика.
Вы можете либо заменить ArrayList
на Vector
, что было бы более простым решением, либо синхронизировать доступ к списку вокруг общего монитор блокировка. Учитывая ваш пример, я использовал бы java.util.Vector
Конечно, вы можете реализовать эти вещи с помощью socket.io и express.
Здесь я хотел бы включить ссылку. Где вы можете увидеть, как просто вы можете создать приложение в реальном времени.
Простое приложение реального времени с использованием socket-io
на стороне сервера:
//-----------------Dependencies------------------
var app = require("express")();
var pgsql = require("pg");
var http = require('http').Server(app);
var io = require("socket.io")(http);
//------------------------------------------------
const con = new pgsql.Pool({
user: 'postgres',
host: 'localhost',
database: 'fbstatus',
password: 'postgres',
port: '5432'
});
app.get("/",function(req,res){
res.sendFile(__dirname + '/index.html');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
// Connect to Postgres
con.connect(function(err, client) {
if(err) {
console.log(err);
}
io.sockets.on('connection', function (socket) {
// Listen for all pg_notify channel messages
client.on('notification', function(msg) {
console.log(msg);
socket.emit('update', msg);
});
// Designate which channels we are listening on. Add additional
channels with multiple lines.
client.query('LISTEN notification_events');
});
});
На стороне клиента: -
<!DOCTYPE html>
<html>
<body>
<h1>real time data recieved from server</h1>
<p>When you insert a new row into database, the below p tag
content will be changed</p>
<p id="socketio"></p>
</body>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('update', function (data) {
var data_got=JSON.parse(data.payload)
console.log(data_got["data"]["id"]);
document.getElementById("socketio").innerHTML = data.payload;
});
</script>
</html>