java的新手无法弄清楚如何使用paint方法

时间:2015-04-03 01:26:09

标签: java swing graphics paint

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

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

这是主要的课程     import java.awt。;     import 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;
}
}

现在当我编译时,我得到一个错误,说在PaintTest类中找不到符号球,即使我是从类Ball调用它。我知道重绘错误,因为我不知道该把它放在它面前。

3 个答案:

答案 0 :(得分:1)

  1. 在JPanel中绘图
  2. 在其绘图方法的paintComponent方法中 - 这会给你双重缓冲。
  3. 在覆盖中调用super的paintComponent方法。这允许JPanel进行管家绘制,包括擦除旧位置的椭圆形图像。
  4. 不要使用while (true)循环,因为这会导致严重的Swing线程问题。改为使用Swing Timer。
  5. 在Swing Timer中,增加动画变量,然后调用repaint()。这将告诉Swing重新绘制将在新位置重新绘制椭圆的组件。
  6. 不要猜测这些东西,因为Swing图形编码是一个不同的野兽导致沮丧。而是检查教程。您可以在此处找到Swing教程和其他Swing资源的链接:Swing Info。另请查看Performing Custom Painting with Swing
  7. Graphics2D好东西:RenderingHints可以用来平滑你的图像锯齿。
  8. 更多Graphics2D好东西:笔画可用于在需要时绘制更粗的线条。

  9. 例如:

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

答案 1 :(得分:0)

您必须将paintComponent方法放在JPanel中。你可以用这样的东西来做到这一点。

JPanel panel = new JPanel(){

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

    }

};

你没有让球在框架中移动的原因是你没有调用重绘方法。 你应该在一个线程上这样做。

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

答案 2 :(得分:-1)

  • 您没有调用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)部分中的毫秒数更改为更小的毫秒数。