簡體   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