关于JPanel功能的担忧:paintcomponent()

2022-09-02 05:22:28

你好,我是java编程的新手,我需要有人向我解释这些代码行:

 public class drawpanel extends JPanel
 {
     public void paintComponent(Graphics g)
     { 
         super.paintComponent(g);
         ...
     }
 }

我不明白这行:如果它在JPanel中预定义,为什么我必须像那样声明该函数?public void paintComponent(Graphics g)

还有这句话:我完全不明白。感谢您的帮助。super.paintComponent(g)


答案 1

基本结构:

关键字表示 继承自 。换句话说,“是一个”。因此,它可以覆盖其方法(未标记的方法)。出于多种原因,您可能希望这样做。例如,您可能希望访问面板的类,您可以使用该类在面板上绘制圆圈、条形图或文本字符串。extendsDrawPanelJPanelDrawPanelJPanelfinalGraphics

如果你不重写任何方法,那么当你扩展时,你会得到这样的东西:JPanel

public class DrawPanel extends JPanel {
    //TODO not much
}

但是,这不是很有用...除非你只是不喜欢这个名字,想改用它(注意:不要那样做)。如果这就是您所拥有的全部,则最好创建 一个 实例,如下所示:JPanelAwesomePanelJPanelJPanel drawPanel = new JPanel();


油漆成分:

扩展 a 的目的是重写该方法。在你覆盖之前,它是不可见的(注意:不可见是使它成为按钮和其他组件的有用容器的原因)。你是对的,该方法是预定义的(如果您想知道,可以在类中),但是该方法所做的就是使一个空 。如果要在面板上绘制某些内容,则需要覆盖它,如下所示:JPanelpaintComponentJPanelpaintComponentpaintComponentJComponentJPanel

public class DrawPanel extends JPanel {
    @Override public void paintComponent(Graphics g) { // <-- HERE!
        //TODO draw stuff
    }
}

注意:该部分不是绝对必要的,但最好包含它,因为它减少了运行时错误的数量,并提高了代码的可读性@Override

您现在可以访问面板的对象。 是一个帮助器类,允许您在面板上绘制内容,如下所示:GraphicsgGraphics

public class DrawPanel extends JPanel {
    @Override public void paintComponent(Graphics g) {
        g.drawOval(50, 50, 50, 50); // <-- draws an oval on the panel
    }
}

super.paintComponent:

有用的比喻(我刚刚编造的):是画布,物体是你的画笔,是你的橡皮擦。(另外, 是你的画架。JPanelGraphicssuper.paintComponent(g)JFrame

因此,从(类)的超类调用方法以擦除面板上当前绘制的任何内容。这对于动画很有用。super.paintComponent(g)paintComponentJPanelJComponent

例如,考虑在面板上绘制一个模拟时钟。您需要每秒刷新一次,因此每一秒您都必须擦除以前的时钟并重新绘制时钟,调整秒针。如果你在重绘时钟之前没有调用,它只会在旧时钟之上继续绘制新时钟,在60秒内,你所拥有的只是一个填充的圆圈,或多或少。super.paintComponent(g)

只有一件事要记住:总是在方法中首先调用,如下所示:super.paintComponent(g)paintComponent

public class DrawPanel extends JPanel {
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // <-- HERE!
        g.drawOval(50, 50, 50, 50);
    }
}

就是这样。请随时与我联系。


例:

我创建了一个简单的示例,使用这些概念在面板(放置在框架内)上显示文本字符串。在 IDE 中另存为 TestPanel.java

import java.awt.*;
import java.util.*;
import javax.swing.*;

/**
 * A frame containing a panel that is sometimes red and sometimes 
 * blue. Also, it displays the word to go with it. 
 * 
 * Inspired by www.sometimesredsometimesblue.com.
 *
 */
public class TestPanel extends JPanel {

    private Random random = new Random();
    private boolean isRed;
    private String s = "";

    public TestPanel() {
        //randomly determine whether the background should be red
        isRed = random.nextBoolean();

        //set the background to blue
        setBackground(Color.BLUE);
        s = "BLUE";

        //if 'isRed' is true, set the background to red
        if (isRed) {
            setBackground(Color.RED);
            s = "RED";
        }
    }

    @Override 
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        //write either "RED" or "BLUE" using graphics
        g.setColor(Color.WHITE);
        g.setFont(new Font("serif", Font.BOLD, 60));
        g.drawString(s, getWidth() / 2 - g.getFontMetrics().stringWidth(s) / 2,
                getHeight() / 2 + g.getFontMetrics().getHeight() / 2);
    }

    //main method: create an instance of TestPanel and output it on a JFrame
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setSize(500, 500);
        f.setTitle("Sometimes Red, Sometimes Blue");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new TestPanel());
        f.setVisible(true);
    }
}

答案 2

paintComponent() 是一种最初在抽象类 JComponent 中定义的方法。直接间接扩展 JComponent 的组件(如果公开)可以选择覆盖 paintComponent()。调用超类的实现(在你的例子中是JPanel的)。如果你想做除了JPanel已经做的事情之外的其他事情,你会想要覆盖。super.paintComponent(g)paintComponent()paintComponent()Graphics g


推荐