【问题标题】:How repaint method differs for a Jpanel and Jframe?Jpanel 和 Jframe 的重绘方法有何不同?
【发布时间】:2014-07-23 19:38:04
【问题描述】:

我有以下代码用于从左上角到右下角为球设置动画。

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class MainFrame{ 
    int i=0,j=0;
    JFrame frame = new JFrame();
    public void go(){   
         Animation anim = new Animation();
         anim.setBackground(Color.red);//Why color is not changing to red for the panel.
         frame.getContentPane().add(anim);
         frame.setVisible(true);
         frame.setSize(475,475);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         for(i=0,j=0;i<frame.getHeight()&&j<frame.getWidth();++i,++j){
               anim.repaint();//Main problem is here,described below.
               try{
                   Thread.sleep(50);
               }
               catch(Exception ex){}
         }
    }
    public static void main(String[] args) {
         MainFrame mf = new MainFrame();
         mf.go();
    }

    class Animation extends JPanel{
         public void paintComponent(Graphics g){
             Graphics2D g2d = (Graphics2D)g;
             g.fillOval(i,j,25,25);
         }
    }
}

问题

  1. 当我在方法go 中执行anim.repaint() 时,我没有让球从左上角动画到右下角,但它会沿着路径涂抹。但是如果我用frame.repaint() 替换它,我会得到想要的结果是一个移动的球。那么这两个对repaint 的调用有什么区别?
  2. 为什么在go 方法中anim.setBackground(Color.red); 之后面板的颜色没有改变?
  3. 如果你运行这个程序,你会发现球并没有完全在底部边缘,那么我怎样才能做到这一点?

【问题讨论】:

  • 不要在 EDT 上睡觉; Concurrency in SwingHow to Use Swing Timers;在这个可能的duplicate 中检查了一个完整的示例。
  • Don't sleep on the EDT - 这总是个好建议,但循环代码实际上并未在 EDT 上执行,因为您没有正确创建 GUI。所有 GUI 组件都应该在 EDT 上创建。这是通过使用上面链接的教程中演示的SwingUtilities.invokeLater() 方法完成的。但是,一旦这样做,您将遇到绘画问题,因为您将导致 EDT 休眠,这意味着在循环结束之前它无法绘制移动的球。因此,您需要按照建议使用计时器。
  • @camickr 做了一个重要的观察:你在initial thread 上睡觉 调用setVisible(); EDT 将开始异步运行,结果将不可预测。

标签: java swing animation background paintcomponent


【解决方案1】:

);//为什么面板的颜色没有变成红色

当您覆盖paintComponent(...) 方法时,您应该始终调用super.paintComponent(g)。默认代码负责绘制背景。

但它会被涂抹在路径上

与上述相同的答案。您需要绘制背景,以便删除所有旧画。

球并没有完全在底部边缘

如果您的意思是球不在面板上的精确对角线上,那是因为您手动设置了框架的大小,并且没有考虑标题栏和边框的大小。如果您希望面板为 (475, 475),则覆盖面板的 getPreferredSize() 方法以返回该尺寸。然后在您的代码中将 frame.setSize() 替换为 frame.pack()

【讨论】:

    猜你喜欢
    • 2016-04-20
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多