【问题标题】:Drawing in JPanel vs JComponent在 JPanel 与 JComponent 中绘图
【发布时间】:2013-06-08 10:12:14
【问题描述】:

我需要一些帮助来理解为什么 JComponent 和 JPanel 中的绘图工作方式不同。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Particle extends JComponent implements Runnable{
    private int x = 45;
    private int y = 45;
    private int cx;
    private int cy;
    private int size;
    private Color color;
    private JFrame frame;

    public Color getColor(){
        return color = new Color(100,0,190);
    }

    public Particle(){
        frame = new JFrame();
        frame.setSize(400, 400);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.setVisible(true);
    }

    public void update(){
        x+=1;
        y+=1;
    }

    public void paintComponent(Graphics g){
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(getColor());

        g2d.fillRect(x, y, 4, 4);
    }

    public void startThread(){
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        for(int i = 0; i <= 200; i++){
            try{
                update();
                repaint();
                Thread.sleep(4);    
            }catch(Exception e){
                System.out.print("Exception at thread.start()");
            }
        }
    }

    public static void main(String[] args) {
        Particle particle = new Particle();
        particle.startThread();
    }
}

在上面这个例子中,“粒子”从 A 点移动到 B 点就好了..

但是当我将 Particle 从 JComponent 子类化到 JPanel 时..

绘图形成一条线..即矩形永远不会从它开始的地方消失..

为什么会这样?

【问题讨论】:

    标签: java swing graphics jpanel jcomponent


    【解决方案1】:

    Toilal 已发布解决方案。我想解释一下为什么

    the API docs of paintComponent of JComponent

    另外,如果你没有调用 super 的实现,你必须遵守 opaque 属性,也就是说,如果这个组件是不透明的,你必须用非透明的颜色完全填充背景。如果您不遵守 opaque 属性,您可能会看到视觉伪影。

    setOpaque of JComponent

    对于JComponent,此属性的默认值为 false。但是,大多数标准 JComponent 子类(例如 JButtonJTree)上此属性的默认值取决于外观。

    添加此代码:

    System.out.println(isOpaque());
    
    • JComponent 的情况下打印false
    • JPanel 的情况下打印true

    就是这样。

    【讨论】:

    • 感谢您的解释。非常感谢。
    • +1,对于这个深刻的信息部分,增加了我的知识:-)
    【解决方案2】:

    在paintComponent实现中调用super.paintComponent(g)。

    public void paintComponent(Graphics g) {
      super.paintComponent(g);
    
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.setColor(getColor());
      g2d.fillRect(x, y, 4, 4);
    
    }
    

    【讨论】:

    • 啊.. 所以 JComponent 自动调用了 super 不是吗?我只是忘了用 JPanel 这样做。另外,我知道每当我重写一个方法时,我都应该像这样调用一个超级......但是你能解释一下当我调用super.paintComponent(g); 时到底发生了什么以及我没有调用它时发生了什么。我这样问是为了更好地了解正在发生的事情。
    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 2012-09-27
    • 2014-01-14
    • 2013-10-07
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多