【问题标题】:problem with super.paintComponent(g)super.paintComponent(g) 的问题
【发布时间】:2011-09-07 21:32:40
【问题描述】:

这是sn-p:

protected void paintComponent(final Graphics g) {

 Runnable r=new Runnable() {

 @Override

  public void run() {
   while(true) {
     super.paintComponent(g);  // <----- line of error
     g.setColor(Color.red);
     g.drawOval(x,y,width,height);
     g.fillOval(x,y,width,height);
     x++;
     y++;
     width++;
     height++;
       if(width==20)
          break;
     try {
        Thread.sleep(100);
     } catch(Exception exc) {
         System.out.println(exc);
       }
   }
  }
};
 Thread moveIt=new Thread(r);
 moveIt.start();
}

编译完整代码时出现以下错误:

d:\UnderTest>javac mainClass.java
mainClass.java:18: cannot find symbol
     super.paintComponent(g);
          ^
symbol:   method paintComponent(Graphics)
location: class Object
1 error

为什么会出现此错误?

如果这是我的完整代码:

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

class movingObjects extends JPanel {
int x=2,y=2,width=10,height=10;

@Override

protected void paintComponent(final Graphics g) {

Runnable r=new Runnable() {

 @Override

  public void run() {
   while(true) {
     super.paintComponent(g);
     g.setColor(Color.red);
     g.drawOval(x,y,width,height);
     g.fillOval(x,y,width,height);
     x++;
     y++;
     width++;
     height++;
       if(width==20)
          break;
     try {
        Thread.sleep(100);
     } catch(Exception exc) {
         System.out.println(exc);
       }
   }
  }
 };
   Thread moveIt=new Thread(r);
    moveIt.start();
    }
   }

class mainClass {

 mainClass() {
 buildGUI();
}

 public void buildGUI() {
 JFrame fr=new JFrame("Moving Objects");
 movingObjects mO=new movingObjects();
 fr.add(mO);
 fr.setVisible(true);
 fr.setSize(400,400); 
 fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

 public static void main(String args[]) {
  new mainClass();
  }
 }  

【问题讨论】:

  • 顺便说一下,从不同的线程调用paintComponent是个坏消息。

标签: java swing user-interface graphics


【解决方案1】:

因为Runnable 没有paintComponent() 方法。这是使用匿名内部类的缺点之一,它很难看到当前上下文是什么,但在你的情况下,上下文是 run() 方法,因此 super 指的是你的匿名内部的超类类,即Runnable

如果你想从一个内部类引用外部类的超类,你应该使用movingObjects.super.paintComponent()

【讨论】:

  • 查看@camickr 的答案。 paintComponent() 可能根本不是你需要重写的方法,事实上你根本不需要做这个线程启动业务。
【解决方案2】:

您应该使用合格的超级。

movingObjects.super.paintComponent(g);

因为,当您在内部类中使用thissuper(在本例中为:Runnable)时,您将获得内部类。如果您想从内部类中使用外部类,请使用 Qualified This 或 Qualified Super。

YourOuterClassName.this
YourOuterClassName.super

合格的超级是我在JLS中找不到的术语,是我自己发明的。

【讨论】:

  • 这可能在技术上回答了为什么代码不能编译的问题,但它不应该被认为是解决你的绘画问题。
  • 那是因为你从来没有更新过屏幕。尝试拨打movingObjects.super.update(g); 之类的电话,这绝对不是正确的方法。如果你想学习正确的方法,你应该了解更多关于 Swing 的知识。观察游戏引擎非常有趣。就个人而言,我喜欢 Ivo Wetzel 的这个:github.com/BonsaiDen/Bonsai-Game-Library
  • 永远不要调用 update(g)。这是用于 AWT 应用程序的旧代码,不应用于 Swing。在 Swing 中,您使用 repaint() 来告诉组件重新绘制自己。
  • 我使用movingObjects.super.update(g); 时出现连续异常!
【解决方案3】:

如果您想在 Swing 面板上显示动画,请使用 Swing Timer

您不应该使用 while (true) 循环,并且该代码绝对不应该是 paintComponent() 方法的一部分或直接调用 paintComponent() 方法。

在您的自定义面板中,您需要设置诸如 setOvalLocation(Point) 之类的属性。然后当 Timer 触发时,您更新椭圆位置并在面板上调用 repaint。

我建议您首先阅读 Custom Painting 上的 Swing 教程,以获得更详细的解释和示例。

【讨论】:

  • 答案太复杂,无法在此详述。组件的属性应在事件调度线程上更新。从我上面提供的链接中查看目录,并阅读“货币”部分了解更多信息。
猜你喜欢
  • 2015-05-09
  • 1970-01-01
  • 2015-04-27
  • 2012-10-18
  • 1970-01-01
  • 2015-12-20
  • 2020-04-14
  • 2018-03-22
  • 1970-01-01
相关资源
最近更新 更多