簡體   English   中英

在繪畫中使用thread.sleep方法

[英]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()方法。 這恰好與您要查找的內容有關。

它遵循的過程是:

  1. 計算上一次更新的時間,並將其存儲在delta
  2. 將上次更新的時間更新為當前時間
  3. 計算deltaX ,即deltaX = delta * velocityX
  4. 計算deltaY ,即deltaY = delta * velocityY
  5. deltaX添加到x這將更新x坐標
  6. 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;
        }

    }
}

它的作用:

抱歉,MadProgrammer,最初需要做首選尺寸

這似乎有點令人不知所措。 逐步執行,更改一些內容。 發瘋,看看結果如何。

也有一些網站可以幫助提高速度以及如何計算這樣的事情。 如果您需要進一步的幫助,只需在下面添加評論,我會做什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM