简体   繁体   English

如何增加重新绘制JPanel的频率?

[英]How do I increase the frequency JPanel is redrawn?

I have a simple program that draws the trajectory of a particle launched from the origin at a certain speed and angle. 我有一个简单的程序,该程序绘制以特定速度和角度从原点发射的粒子的轨迹。 I created a subclass of JPanel to handle the drawing of this. 我创建了JPanel的子类来处理此绘图。 My everytime my subclass is redrawn it takes the difference between the current time and the initial time(both in milliseconds), converts this to seconds, then finds the x and y coordinate of where the particle should be at that point in time, and finally takes those x and y coordinates and draws them on the screen. 每次重绘子类时,它都会获取当前时间与初始时间之间的差(均以毫秒为单位),将其转换为秒,然后找到粒子在该时间点应位于的x和y坐标,最后获取这些x和y坐标并将它们绘制在屏幕上。 My problem is that my subclass seems to be redrawn at interval that seem long because there are only a few dots that are shown. 我的问题是我的子类似乎以很长的间隔重绘,因为只显示了几个点。

My drawing method: 我的绘画方法:

private void doDrawing(Graphics g) {

    Dimension size = getSize();
    Insets insets = getInsets();
    int w = size.width - insets.left - insets.right;
    int h = size.height - insets.top - insets.bottom;

    Graphics2D g2d = (Graphics2D) g;
    g.drawString("Acceleration: -9.8m/s i", 0, 20);
    StringBuilder b = new StringBuilder();
    b.append("Current Velocity: ");
    b.append(String.valueOf(sim.getVector(tickSpeed
            * ((System.currentTimeMillis() - initTime) / 1000)).getMagnitude()));
    b.append(" m/s at ");
    b.append(String.valueOf(sim.getVector(tickSpeed
            * ((System.currentTimeMillis() - initTime) / 1000)).getDirection().getDirectionDeg()));
    b.append(" degrees");
    g.drawString(b.toString(), 0, 30);

    drawPreviousPoints(g2d);

    drawCurrentPointAndAppend(g2d, w, h);

    repaint();

}

private void drawCurrentPointAndAppend(Graphics2D g2d, int w, int h) {
    g2d.setColor(Color.red);
    double height = (length / w) * h;
    Vector2D c = sim.getVector(tickSpeed
            * ((System.currentTimeMillis() - initTime) / 1000));
    double currentX = w
            * ((sim.getX(tickSpeed
                    * ((System.currentTimeMillis() - initTime) / 1000))) / length);
    double currentY = h
            * (1 - ((sim.getY(tickSpeed
                    * ((System.currentTimeMillis() - initTime) / 1000))) / height));

    g2d.drawLine((int) currentX, (int) currentY, (int) currentX,
            (int) currentY);
    g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
            BasicStroke.JOIN_MITER));
    g2d.drawLine((int) currentX, (int) (currentY),
            (int) (currentX + w * (c.getX() / length)),
            (int) (currentY + (h *  -(c.getY() / height))));
    xList.add(currentX);
    yList.add(currentY);

}

private void drawPreviousPoints(Graphics2D g2d) {
    g2d.setColor(Color.blue);
    g2d.setStroke(new BasicStroke(7, BasicStroke.CAP_ROUND,
            BasicStroke.JOIN_ROUND));
    if (!xList.isEmpty()) {
        for (int i = 0; i < xList.size(); i++) {
            g2d.drawLine(xList.get(i).intValue(), yList.get(i).intValue(),
                    xList.get(i).intValue(), yList.get(i).intValue());
        }
    }

}

tickSpeed is just a variable that I use to speed up or slow down the particle. tickSpeed只是我用来加快或减慢粒子速度的变量。 It runs fine; 运行良好; however, the animation seems very choppy. 但是,动画看起来非常不稳定。

  • How do I fix this choppiness(make everything seem more "fluid") 我该如何解决此问题(使所有内容看起来都更“流畅”)
  • Where should I call repaint()? 我应该在哪里调用repaint()? Because I feel like calling it at the end of my drawing method isn't right. 因为我想在绘图方法的结尾处​​调用它是不正确的。

An important rule of Swing- You don't control the paint process... Swing的重要规则-您无需控制涂漆过程...

Don't perform these calculations within the paintComponent . 不要在paintComponent执行这些计算。 The paintComponent is meant to paint the current state of the UI and may be called at any time for many reasons, most of which are outside your control. paintComponent用于绘制UI的当前状态,并且由于多种原因可以随时调用,其中大多数是您无法控制的。

Instead, consider using a javax.swing.Timer set to repeat at a regular interval (40ms is 25 ticks a second). 相反,可以考虑使用javax.swing.Timer设置为以规则的间隔重复(40ms是每秒25个滴答)。

Set up a model which keeps track of the particles current been processed. 建立一个模型,以跟踪当前处理的粒子。 When the timer ticks, calculate your particle positions and update them, then call repaint . 当计时器计时时,计算您的粒子位置并更新它们,然后调用repaint

Within your paintComponent , simply paint the current state of your model. paintComponent ,只需绘制模型的当前状态。

Have a look at Concurrency in Swing and How to use Swing Timers for more details 了解Swing中的并发性以及如何使用Swing计时器以了解更多详细信息

The paint process is internally handled so you can not control the frequency of it's execution. 绘制过程是内部处理的,因此您无法控制其执行的频率。 However, you can create separate threads or timers which can invoke processes at your desired frequency. 但是,您可以创建单独的线程或计时器,以所需的频率调用进程。 Use the paint method only to render on your canvas, do other logic and processing in another function. 仅使用paint方法在画布上进行渲染,在其他函数中执行其他逻辑和处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM