繁体   English   中英

Java新手无法弄清楚如何使用绘画方法

[英]New to java can't figure out how to use paint method

我正在尝试学习绘画方法,并使球在框架上移动。 到目前为止,这是我的代码。 w =。

我目前有两个班级,一个是主班,一个是球班。

这是导入java.awt的主要类。 ; 导入javax.swing。 ;

public class PaintTest extends JPanel {
int x = 0;
int y = 0;

public void moveBall(){
    x = x + 1;
    y = y + 1;
}
public static void main(String[] args){
    JFrame frame = new JFrame();
    frame.setSize(500,500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    Ball ball = new Ball(x,y);

    while(true){
        ball.moveBall();
        repaint();
    }
    }
protected void paintComponent(Graphics g){
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g;

    g.setColor(Color.magenta);
    g.drawLine(0,100,500,100);
    g.drawLine(0,101,500,101);
    g.drawLine(0,102,500,102);
    g.drawLine(0,103,500,103);

    g2.fillOval(x,y,35,35);
}
}

这是球课

 public class Ball {

   int x,y;

   public Ball(int x, int y){
this.x = x;
this.y = y;
}
}

现在,当我进行编译时,出现错误消息,即使我从Ball类调用它也无法在PaintTest类中找到符号ball。 我知道重画错误,因为我不知道在它前面放什么。

  1. 在JPanel中绘制
  2. 在其paintComponent方法中而不是在其paint方法中—这为您提供了双重缓冲。
  3. 在您的覆盖中调用上级的paintComponent方法。 这使JPanel可以做家政绘图,包括在其旧位置删除椭圆形图像。
  4. 不要使用while (true)循环,因为这可能会导致严重的Swing线程问题。 请改用Swing计时器。
  5. 在Swing计时器中,增加动画变量,然后调用repaint() 这将告诉Swing重新绘制组件,这将在新位置重新绘制椭圆形。
  6. 不要猜这些东西,因为Swing图形编码是另一种野兽,这会导致沮丧。 而是查看教程。 您可以在此处找到Swing教程和其他Swing资源的链接: Swing信息 另请参阅使用Swing执行自定义绘画
  7. Graphics2D好东西:RenderingHints可用于消除图像锯齿。
  8. 更多Graphics2D好东西:可以在需要时使用笔触绘制粗线。

例如:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

@SuppressWarnings("serial")
public class PaintTest extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = PREF_W;
   private static final int TIMER_DELAY = 20;
   private static final Stroke STROKE = new BasicStroke(5f);
   private int x;
   private int y;

   public PaintTest() {
      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;

      // to smooth graphics
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      g2.setColor(Color.magenta);
      Stroke initialStroke = g2.getStroke();
      g2.setStroke(STROKE);
      g.drawLine(0, 100, 500, 100);
      g2.setStroke(initialStroke);

      g2.fillOval(x, y, 35, 35);
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         x++;
         y++;
         repaint();
      }
   }

   private static void createAndShowGui() {
      PaintTest mainPanel = new PaintTest();

      JFrame frame = new JFrame("PaintTest");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

您必须将paintComponent方法放入JPanel中。 您可以使用类似的方法来做到这一点。

JPanel panel = new JPanel(){

    @Overide
    public void paintComponent(Graphics g){
        super.paint();
        // Draw Stuff Here

    }

};

您没有使球在框架上移动的原因是您没有调用repaint方法。 您应该在线程上执行此操作。

Thread th = new Thread(new Runnable(){
    @Overide
    public void run(){
        while(frame.isVisible()){
            ball.moveBall();     
            panel.repaint();
            try{Thread.sleep(5);}catch(Exception e){e.printStackTrace();}
        }
    }
});

另外,为什么要使ball成为PaintTest类的实例? 要只获得一个框架和球,您需要添加一个名为Ball的类,并使用该类创建一个实例:

public class Ball{

    int x, y;

    public Ball(int x, int y){
        this.x = x;
        this.y = y;
    }
} 

这就是为什么要获得2帧的原因。

然后,您将希望摆脱主类中的x和y变量。 要使用此类创建实例,您可以执行以下操作:

Ball ball = new Ball(x, y);

然后在paintComponent方法中绘制球:

g.fillOval(ball.x, ball.y, 35, 35);
  • 您没有调用repaint(); 方法。
  • 您不需要y + 1部分。
  • 不要使用while(true)循环,而应该使用for循环。
  • 您没有调用super.paint()方法。
  • 您没有使用任何Thread.sleep() ,它使球瞬间移动。

这是代码:

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

public class PaintTest extends JFrame {
int x = 8;
int y = 30;

public void moveBall(){
x = x + 1;
//y = y + 1;
try{
    Thread.sleep(500);
} catch(InterruptedException e){

}
repaint();
}
public static void main(String[] args){
PaintTest frame1 = new PaintTest();
PaintTest ball = new PaintTest();

for(int i = 0; i<100; i++){
//while(true){
    ball.moveBall();
}
}

public PaintTest() {
super("Paint Test");
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


setVisible(true);
}

public void paint(Graphics g){

Graphics2D g2 = (Graphics2D) g;
super.paint(g);
super.paint(g2);
g.setColor(Color.magenta);
g.drawLine(0,100,500,100);
g.drawLine(0,101,500,101);
g.drawLine(0,102,500,102);
g.drawLine(0,103,500,103);

g.fillOval(x,y,35,35);
}
}

此代码将使球非常缓慢地在屏幕上移动。 如果要加快速度,请将Thread.sleep(miliseconds)部分中的毫秒数更改为较小的毫秒数。

暂无
暂无

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

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