[英]Using the thread.sleep method in painting
我有一個工作代碼,基本上可以在屏幕上繪制15個矩形,您可以在其中拖動。 我這樣做是為了使矩形隨着時間的流逝落在屏幕的底部。 當我使用thread.sleep方法時,可以使用較大的數字(例如500),但是當矩形掉落時,我仍然可以在屏幕上拖動矩形,沒有問題。 但是隨着我開始將thread.sleep方法減少到較小的數字(例如50),突然出現了問題。 諸如此類的問題,例如,我只能將最多2個矩形拖到矩形上,然后再開始將其拖回我沒有拖動它們的地方。 有時,我最多只能拖動一個矩形,一旦選擇了該矩形,便無法選擇其他任何矩形進行拖動。 我知道我的代碼絕對正確,因為它可以在thread.sleep方法使用較大數字時起作用,所以我的問題是:當我將thread.sleep設置為較小數字時,為什么它會開始出現毛刺? 這是我的代碼的一部分。
while (true) {
for (int i = 0; i < 15; i++) {
P.fY[i]++;
}
Thread.sleep(500);
frame.repaint();
} //the 15 stands for 15 rectangles, and the P.fY stands for the position of y.
因此,根據您的評論,您似乎真的需要幫助弄清楚如何根據時間來計算距離。
通過每幀增加1
個循環,您實際上是在說每個方塊的速度是1 pixel / 1 frame
。
取而代之的是,您應該利用時間並通過時間的函數來更新距離,以使其為1 pixel / unit of time
。 這意味着方格的速度將獨立於每秒的幀數。
我整理了一個代碼示例。 重要的方法是Square#doUpdate()
方法。 這恰好與您要查找的內容有關。
它遵循的過程是:
- 計算上一次更新的時間,並將其存儲在
delta
。- 將上次更新的時間更新為當前時間
- 計算
deltaX
,即deltaX = delta * velocityX
- 計算
deltaY
,即deltaY = delta * velocityY
- 將
deltaX
添加到x
這將更新x
坐標- 向
y
添加deltaY
這將更新y
坐標
代碼如下:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
/**
* @author Obicere
*/
public class MovingSquare {
private volatile int viewportWidth;
private volatile int viewportHeight;
private final LinkedList<Square> squares = new LinkedList<>();
public MovingSquare() {
final JFrame frame = new JFrame("Moving Square");
final JPanel displayPanel = new JPanel() {
@Override
protected void paintComponent(final Graphics g) {
synchronized (squares) {
for (final Square square : squares) {
// Update the square's locations, ideally this will
// be separate of the painting thread
square.doUpdate();
final int x = (int) square.getX();
final int y = (int) square.getY();
g.setColor(square.getColor());
g.drawRect(x, y, square.squareSize, square.squareSize);
}
}
}
};
displayPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent e) {
final Color nextColor = Color.getHSBColor((float) Math.random(), 1, 0.5f);
final float speedX = (float) Math.random();
final float speedY = (float) Math.random();
synchronized (squares) {
final Square newSquare = new Square(nextColor, speedX, speedY);
squares.add(newSquare);
newSquare.x = e.getX();
newSquare.y = e.getY();
}
}
});
displayPanel.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
viewportWidth = displayPanel.getWidth();
viewportHeight = displayPanel.getHeight();
}
});
final Timer repaintTimer = new Timer(20, null);
repaintTimer.addActionListener(e -> {
if (!frame.isVisible()) {
repaintTimer.stop();
return;
}
frame.repaint();
});
repaintTimer.start();
displayPanel.setPreferredSize(new Dimension(200, 200)); // Sorry MadProgrammer
frame.add(displayPanel);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(MovingSquare::new);
}
private class Square {
private final int squareSize = 25;
private volatile float x;
private volatile float y;
private volatile long lastUpdateTime;
private volatile boolean negateX;
private volatile boolean negateY;
private final float speedX;
private final float speedY;
private final Color color;
public Square(final Color color, final float speedX, final float speedY) {
this.color = color;
this.speedX = speedX;
this.speedY = speedY;
lastUpdateTime = System.currentTimeMillis();
}
/**
* Important method here!!
* <p>
* This updates the location of the squares based off of a set
* velocity and the difference in times between updates.
*/
public void doUpdate() {
// Gets the change in time from last update
final long currentTime = System.currentTimeMillis();
final long delta = currentTime - lastUpdateTime;
if (delta == 0) {
return;
}
// be sure to update the last time it was updated
lastUpdateTime = currentTime;
// Calculate the speed based off of the change in time
final float deltaX = getSpeedX(delta);
final float deltaY = getSpeedY(delta);
// Move each square by the change of distance, calculated from
// the change in time and the velocity.
final float nextX = x + deltaX;
final float nextY = y + deltaY;
handleBouncing(nextX, nextY);
}
private void handleBouncing(final float nextX, final float nextY) {
if (nextX < 0) {
x = 0;
flipX();
} else if (nextX + squareSize >= viewportWidth) {
x = viewportWidth - squareSize;
flipX();
} else {
x = nextX;
}
if (nextY < 0) {
y = 0;
flipY();
} else if (nextY + squareSize >= viewportHeight) {
y = viewportHeight - squareSize;
flipY();
} else {
y = nextY;
}
}
private float getSpeedX(final long delta) {
return (negateX ? -1 : 1) * delta * speedX;
}
private float getSpeedY(final long delta) {
return (negateY ? -1 : 1) * delta * speedY;
}
protected void flipX() {
negateX = !negateX;
}
protected void flipY() {
negateY = !negateY;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public Color getColor() {
return color;
}
}
}
它的作用:
這似乎有點令人不知所措。 逐步執行,更改一些內容。 發瘋,看看結果如何。
也有一些網站可以幫助提高速度以及如何計算這樣的事情。 如果您需要進一步的幫助,只需在下面添加評論,我會做什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.