简体   繁体   English

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

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

I am trying to learn the paint method and get a ball to move across the frame. 我正在尝试学习绘画方法,并使球在框架上移动。 here is my code so far. 到目前为止,这是我的代码。 w=. w =。

I currently have two classes One is the main and one for the ball. 我目前有两个班级,一个是主班,一个是球班。

this is the main class import java.awt. 这是导入java.awt的主要类。 ; ; import javax.swing. 导入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);
}
}

and here is the ball class 这是球课

 public class Ball {

   int x,y;

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

now when i compile I get an error saying cannot find symbol ball in class PaintTest even though I am calling it from the class Ball. 现在,当我进行编译时,出现错误消息,即使我从Ball类调用它也无法在PaintTest类中找到符号ball。 I am aware of the repaint error as i do not know what to put in front of it. 我知道重画错误,因为我不知道在它前面放什么。

  1. Draw in a JPanel 在JPanel中绘制
  2. In its paintComponent method not in its paint method -- this gives you double buffering. 在其paintComponent方法中而不是在其paint方法中—这为您提供了双重缓冲。
  3. Call the super's paintComponent method in your override. 在您的覆盖中调用上级的paintComponent方法。 This allows the JPanel to do housekeeping drawing including erasing the oval image at its old position. 这使JPanel可以做家政绘图,包括在其旧位置删除椭圆形图像。
  4. Don't use a while (true) loop as this can cause serious Swing threading issues. 不要使用while (true)循环,因为这可能会导致严重的Swing线程问题。 Use a Swing Timer instead. 请改用Swing计时器。
  5. In the Swing Timer, increment your animation variables and then call repaint() . 在Swing计时器中,增加动画变量,然后调用repaint() This will tell Swing to repaint the component which will re-draw the oval in the new location. 这将告诉Swing重新绘制组件,这将在新位置重新绘制椭圆形。
  6. Don't guess at this stuff as that leads to frustration since Swing graphics coding is a different beast. 不要猜这些东西,因为Swing图形编码是另一种野兽,这会导致沮丧。 Instead check the tutorials. 而是查看教程。 You can find links to the Swing tutorials and to other Swing resources here: Swing Info . 您可以在此处找到Swing教程和其他Swing资源的链接: Swing信息 Also check out Performing Custom Painting with Swing . 另请参阅使用Swing执行自定义绘画
  7. Graphics2D goodies: RenderingHints can be used to smooth out your image jaggies. Graphics2D好东西:RenderingHints可用于消除图像锯齿。
  8. More Graphics2D goodies: Stroke can be used to draw thicker lines when needed. 更多Graphics2D好东西:可以在需要时使用笔触绘制粗线。

For example: 例如:

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();
         }
      });
   }
}

You have to put the paintComponent method in a JPanel. 您必须将paintComponent方法放入JPanel中。 You can do it by using something like this. 您可以使用类似的方法来做到这一点。

JPanel panel = new JPanel(){

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

    }

};

The reason you are not getting the ball to move across the frame is that you are not calling the repaint method. 您没有使球在框架上移动的原因是您没有调用repaint方法。 You should do so on a thread. 您应该在线程上执行此操作。

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();}
        }
    }
});

Also, why are you making ball a instance of the PaintTest class? 另外,为什么要使ball成为PaintTest类的实例? To get only one frame and ball you would want to add a class named Ball and use that to make an instance: 要只获得一个框架和球,您需要添加一个名为Ball的类,并使用该类创建一个实例:

public class Ball{

    int x, y;

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

That is why you were getting 2 frames. 这就是为什么要获得2帧的原因。

Then you would want to get rid of the x and y variables in the main class. 然后,您将希望摆脱主类中的x和y变量。 To make an instance using this class you would do: 要使用此类创建实例,您可以执行以下操作:

Ball ball = new Ball(x, y);

Then to paint the ball in the paintComponent method you would do: 然后在paintComponent方法中绘制球:

g.fillOval(ball.x, ball.y, 35, 35);
  • You didn't call the repaint(); 您没有调用repaint(); method. 方法。
  • You don't need the y + 1 part. 您不需要y + 1部分。
  • Instead of using the while(true) loop, you should use a for loop. 不要使用while(true)循环,而应该使用for循环。
  • You didn't call the super.paint() method. 您没有调用super.paint()方法。
  • You didn't use any Thread.sleep() , which made the ball move across instantaneously. 您没有使用任何Thread.sleep() ,它使球瞬间移动。

Here is the code: 这是代码:

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);
}
}

This code will make the ball move across the screen VERY slowly. 此代码将使球非常缓慢地在屏幕上移动。 If you want to speed it up, change the number of miliseconds in the Thread.sleep(miliseconds) part to a smaller number of miliseconds. 如果要加快速度,请将Thread.sleep(miliseconds)部分中的毫秒数更改为较小的毫秒数。

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

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