繁体   English   中英

用Java绘制并移动一个圆圈

[英]Draw and move a circle in Java

我正在使用Swing在Java中创建一个小型GUI。 我试图让它做的就是获取CircleArrayList并绘制它们。 我遇到了两个问题:

1)我必须在绘制圆圈之前反复调用我的draw方法。 如果我只是在没有任何反应时调用我的draw方法,我会得到一张空白图纸。 如果我在一个运行时间小于30毫秒的循环中调用它,它只会绘制我想要绘制的两个圆圈中的第一个。 最后,如果我调用它超过30毫秒,它会绘制我试图绘制的两个圆圈。

2)当我移动其中一个圆圈时,我在绘图上出现“闪烁”。

我对Swing编程不太熟悉。 我查看了示例代码并观看了一些视频 - 以及我对我的看法。 但我认为我一定搞砸了,因为在我看过的视频中看起来并不像这样。

这是我的GUI类:

package gui;

import draw.*;
import java.util.List;
import javax.swing.*;

public class GUI extends JFrame {
    private CirclePainter drawingBoard = new CirclePainter();

    public GUI()
    {
        setSize(500, 500);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.add(drawingBoard);
        drawingBoard.setVisible(true);
    }

    public void draw(List<Circle> circles)
    {
        drawingBoard.paintComponent(drawingBoard.getGraphics(), circles);
    }
}

我的CirclePainter课程

package gui;

import draw.Circle;

import javax.swing.*;
import java.awt.*;
import java.util.List;

class CirclePainter extends JPanel
{
    public void paintComponent(Graphics graphics, List<Circle> circles)
    {
        super.paintComponent(graphics);
        for(Circle circle : circles)
            graphics.fillOval(circle.getX(), circle.getY(), circle.getRadius() * 2, circle.getRadius() * 2);
    }
}

编辑:编辑一些代码,因为这是一个学校项目。 剩下的代码应该足以让将来访问的人仍然能够理解这个问题。

  1. 永远不要直接调用paintComponent(...)
  2. 而是在必要时通过在组件上调用repaint()来建议绘制。
  3. 不要使用通过组件上的getGraphics()调用获得的Graphics对象进行绘制。 而是使用paintComponent方法中提供的Graphics对象进行绘制。
  4. 避免在Swing GUI中使用while (true)循环,因为您可能会占用Swing事件线程并冻结GUI。 使用Swing Timer进行简单的动画制作。
  5. 您可能甚至不需要Swing Timer,因为您的动画可以由MouseListener / MouseMotionListener驱动。
  6. 重要的是 - 请阅读Swing绘画和其他教程,因为大部分信息都可以在那里找到。 看起来你在猜测如何编写一些代码,在绘制或动画GUI时这是一件危险的事情。 您可以在Swing信息链接中找到大多数教程。
  7. 考虑使用Shape对象来表示Circle,例如ellipse2D。 这有助于它有一些非常有用的方法,包括一个contains(Point p)方法,可以帮助您确定鼠标点击是否落在您的圆圈内。
  8. 您需要决定_x和_y在哪里代表圆圈的中心点 如果是这样,那么你需要通过向左和向上移动_radius量来调整你的绘图。
  9. 考虑将Graphics对象转换为Graphics2D对象,以便使用其额外的方法和属性。
  10. 其中一个属性是RenderingHings。 设置你的Graphics2D RenderingHints以允许消除锯齿以摆脱你的图像“锯齿”。 这可以通过以下方式完成: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 其中g2是你的Graphics2D对象。
  11. 您的paintComponent方法不是真正的paintComponent覆盖,因此将无法正常工作。 它应该是protected方法,而不是public ,它应该有一个参数,一个Graphics对象,以及nto第二个参数,你应该在它上面放置@Override注释。

例如,请看一下类似问题的答案

paintComponent方法的一个示例,它将圆圈居中于_x和_y并使用渲染提示:

class CirclePainter extends JPanel implements Iterable<Circle> {
   private static final int PREF_W = 500;
   private static final int PREF_H = PREF_W;
   private CircleList circleList = new CircleList();

   @Override
   protected void paintComponent(Graphics graphics) {
      super.paintComponent(graphics);
      Graphics2D g2 = (Graphics2D) graphics;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      for (Circle circle : circleList) {
         // if x and y are the center points, then you must subtract the radius.
         int x = circle.getX() - circle.getRadius();
         int y = circle.getY() - circle.getRadius();
         int width = circle.getRadius() * 2;
         int height = width;
         g2.fillOval(x, y, width, height);
      }
   }

基于您的代码和来自Hovercraft Full Of Eels的建议,可以通过对GUI和CirclePainter类的这些修改向正确的方向迈出一小步:

// GUI.draw
public void draw(List<Circle> circles)
{
//    drawingBoard.paintComponent(drawingBoard.getGraphics(), circles);
    drawingBoard.setCircles(circles);
    drawingBoard.repaint();
}


class CirclePainter extends JPanel
{
//    public void paintComponent(Graphics graphics, List<Circle> circles)
//    {
//        super.paintComponent(graphics);
//        for(Circle circle : circles)
//            graphics.fillOval(circle.getX(), circle.getY(), circle.getRadius() * 2, circle.getRadius() * 2);
//    }

    private List<Circle> circles;

    public void setCircles(final List<Circle> circles) {
        this.circles = circles;
    }

    @Override
    protected void paintComponent(final Graphics graphics) {
        super.paintComponent(graphics);
        for (Circle circle : circles)
            graphics.fillOval(circle.getX(), circle.getY(), circle.getRadius() * 2, circle.getRadius() * 2);
    }
}

这样,您可能没有解决所有基本问题,但是您只需稍作更改即可使程序正常运行。 而Swing是一个非常好的图书馆,可以很有趣地了解更多。

暂无
暂无

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

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